@apexnative/navigation 1.0.0-alpha.5 → 1.0.0-alpha.7
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/ApexNavigation.podspec +2 -1
- package/CHANGELOG.md +32 -0
- package/README.md +1 -1
- package/android/CLAUDE.md +31 -20
- package/android/CORE.md +12 -8
- package/android/consumer-rules.pro +6 -0
- package/android/src/main/java/dev/apexnative/navigation/NavigationActivity.kt +36 -5
- package/android/src/main/java/dev/apexnative/navigation/options/BottomTabOptions.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/BottomTabsOptions.kt +13 -8
- package/android/src/main/java/dev/apexnative/navigation/options/ButtonOptions.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/LargeTitleOptions.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/LayoutAnimation.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/OptionKey.kt +18 -0
- package/android/src/main/java/dev/apexnative/navigation/options/OptionPaths.kt +91 -0
- package/android/src/main/java/dev/apexnative/navigation/options/SheetOptions.kt +7 -4
- package/android/src/main/java/dev/apexnative/navigation/options/TitleOptions.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/TopBarAppearanceOptions.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/TopBarOptions.kt +16 -7
- package/android/src/main/java/dev/apexnative/navigation/react/ContentHeights.kt +95 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ContentMounts.kt +66 -0
- package/android/src/main/java/dev/apexnative/navigation/react/NavigationTurboModule.kt +7 -3
- package/android/src/main/java/dev/apexnative/navigation/react/OptionsCommands.kt +41 -3
- package/android/src/main/java/dev/apexnative/navigation/react/ReactView.kt +16 -1
- package/android/src/main/java/dev/apexnative/navigation/react/ReloadCoordinator.kt +0 -2
- package/android/src/main/java/dev/apexnative/navigation/react/ScreenEnvironment.kt +177 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ScreenRegions.kt +12 -49
- package/android/src/main/java/dev/apexnative/navigation/react/ScrollEvents.kt +49 -128
- package/android/src/main/java/dev/apexnative/navigation/safearea/SafeAreaView.kt +6 -6
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotScreenView.kt +27 -7
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotView.kt +12 -1
- package/android/src/main/java/dev/apexnative/navigation/utils/MaterialTheme.kt +5 -6
- package/android/src/main/java/dev/apexnative/navigation/utils/SystemAnimations.kt +36 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/ViewExtensions.kt +0 -13
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementController.kt +9 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsCollapseBehavior.kt +5 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsController.kt +13 -10
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowGeometry.kt +22 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabsRoom.kt +0 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentViewController.kt +7 -8
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenSafeArea.kt +29 -11
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/externalcomponent/ExternalComponentViewController.kt +2 -6
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalCoordinator.kt +20 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalSheet.kt +443 -58
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalViews.kt +33 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetBack.kt +42 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetStops.kt +60 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/Navigator.kt +4 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ParentController.kt +3 -6
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuMotion.kt +8 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/BackPreview.kt +32 -4
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/PreparedFrame.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackCommands.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackController.kt +50 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackQueue.kt +15 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackViews.kt +10 -4
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabMotion.kt +142 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabPresenter.kt +215 -43
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/StackSearchPresenter.kt +25 -26
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarRowTransition.kt +3 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/ButtonPlaces.kt +11 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarPresenter.kt +36 -38
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ScrollEventListener.kt +6 -9
- package/android/src/main/java/dev/apexnative/navigation/views/animations/AnimationLayer.kt +73 -0
- package/android/src/main/java/dev/apexnative/navigation/views/animations/ValueInterpolation.kt +14 -0
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabsLayout.kt +61 -2
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomTabRow.kt +72 -10
- package/android/src/main/java/dev/apexnative/navigation/views/element/ElementTransitions.kt +129 -179
- package/android/src/main/java/dev/apexnative/navigation/views/element/TargetsWait.kt +8 -1
- package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionLayer.kt +37 -112
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ElementPictures.kt +67 -3
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/FlightGeometry.kt +346 -36
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMorph.kt +199 -0
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/SharedAnimatorFactory.kt +55 -42
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextMorph.kt +176 -0
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewMorph.kt +108 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabCopy.kt +85 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabMenu.kt +13 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TitleBar.kt +5 -24
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TopBar.kt +51 -34
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonComponentCell.kt +6 -6
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonView.kt +113 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarMenu.kt +219 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonBar.kt +121 -175
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonMenus.kt +34 -64
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonRow.kt +216 -0
- package/android/src/main/jni/ANNContentHeights.cpp +82 -0
- package/android/src/main/res/drawable/apex_navigation_ic_arrow_right.xml +14 -0
- package/android/src/main/res/layout/apex_navigation_menu_header.xml +19 -0
- package/android/src/main/res/layout/apex_navigation_menu_item.xml +68 -0
- package/android/src/main/res/values/styles.xml +1 -1
- package/android/src/main/res/values-night/styles.xml +1 -1
- package/cli/doctor/checks/app.js +16 -1
- package/cli/project.js +4 -0
- package/cli/setup/index.js +5 -0
- package/cli/setup/steps/metro.js +46 -0
- package/docs-md/architecture/native-screens.md +4 -0
- package/docs-md/architecture/theme-and-context.md +131 -12
- package/docs-md/architecture/transitions.md +46 -5
- package/docs-md/containers/modals.md +2 -0
- package/docs-md/containers/overlays.md +1 -1
- package/docs-md/containers/side-menu.md +1 -1
- package/docs-md/containers/tabs.md +2 -0
- package/docs-md/flows/bottom-sheets.md +4 -2
- package/docs-md/fundamentals/screens-and-props.md +9 -1
- package/docs-md/fundamentals/starting-the-app.md +1 -1
- package/docs-md/guides/cli.md +3 -1
- package/docs-md/help/glossary.md +2 -2
- package/docs-md/help/troubleshooting.md +22 -1
- package/docs-md/index.json +41 -1
- package/docs-md/migration/from-expo-router.md +1 -1
- package/docs-md/migration/from-react-native-navigation.md +1 -1
- package/docs-md/migration/from-react-navigation.md +2 -2
- package/docs-md/screen-ui/back-and-gestures.md +17 -1
- package/docs-md/screen-ui/bar-buttons.md +5 -5
- package/docs-md/screen-ui/search.md +1 -1
- package/docs-md/screen-ui/system-ui.md +16 -11
- package/docs-md/screen-ui/toolbar-and-fab.md +4 -2
- package/docs-md/screen-ui/top-bar.md +8 -4
- package/docs-md/start/installation.md +16 -1
- package/ios/Animations/ANNFrameDriver.h +55 -15
- package/ios/Animations/ANNFrameDriver.mm +216 -60
- package/ios/Animations/ANNTransitionAnimator.h +26 -5
- package/ios/Animations/ANNTransitionAnimator.mm +49 -3
- package/ios/Animations/ANNTransitionPlan.h +2 -2
- package/ios/Animations/ANNTransitionPlan.mm +10 -0
- package/ios/Animations/Elements/ANNElementFinder.h +2 -2
- package/ios/Animations/Elements/ANNElementFinder.mm +2 -2
- package/ios/Animations/Elements/ANNElementTransition.h +3 -3
- package/ios/Animations/Elements/ANNElementTransition.mm +2 -2
- package/ios/Animations/Elements/ANNSharedElementFlight.h +3 -3
- package/ios/Animations/Elements/ANNSharedElementFlight.mm +249 -45
- package/ios/Animations/Interpolators/ANNInterpolate.h +2 -30
- package/ios/Animations/Interpolators/ANNTransformParts.h +48 -0
- package/ios/Animations/Interpolators/ANNTransformParts.mm +507 -0
- package/ios/Animations/Interpolators/ANNViewTracks.h +9 -6
- package/ios/Animations/Interpolators/ANNViewTracks.mm +100 -30
- package/ios/CLAUDE.md +32 -22
- package/ios/CORE.md +25 -21
- package/ios/Contract/ANNCommandRunner.h +8 -7
- package/ios/Contract/ANNCommandRunner.mm +21 -27
- package/ios/Contract/ANNLayoutNode.h +3 -3
- package/ios/Contract/ANNLayoutReader.h +3 -3
- package/ios/Core/ANNAppDelegate.mm +0 -2
- package/ios/Core/ANNDeepLinkQueue.h +6 -5
- package/ios/Core/ANNDeepLinkQueue.mm +22 -10
- package/ios/Core/ANNJavaScriptCalls.h +11 -12
- package/ios/Core/ANNJavaScriptCalls.mm +7 -16
- package/ios/Core/ANNReloadCoordinator.mm +4 -8
- package/ios/Core/ANNSceneDelegate.mm +2 -2
- package/ios/Core/ApexNavigation+Internal.h +1 -1
- package/ios/Core/ApexNavigation.mm +6 -2
- package/ios/Layouts/Arrangement/ANNArrangementState.h +2 -17
- package/ios/Layouts/Arrangement/ANNArrangementState.mm +0 -38
- package/ios/Layouts/Arrangement/ANNArrangementViewController.mm +4 -4
- package/ios/Layouts/Root/ANNRootCoordinator.mm +45 -15
- package/ios/Layouts/Screen/ANNComponentViewController.h +2 -2
- package/ios/Layouts/Screen/ANNComponentViewController.mm +13 -23
- package/ios/Layouts/Screen/ANNPreviewInteraction.h +7 -4
- package/ios/Layouts/Screen/ANNPreviewInteraction.mm +72 -10
- package/ios/Layouts/Screen/ANNScreenEnvironment.h +63 -0
- package/ios/Layouts/Screen/ANNScreenEnvironment.mm +181 -0
- package/ios/Layouts/Screen/ANNScreenRegions.h +3 -18
- package/ios/Layouts/Screen/ANNScreenRegions.mm +0 -38
- package/ios/Layouts/Screen/ANNScreenSafeArea.h +4 -9
- package/ios/Layouts/Screen/ANNScreenSafeArea.mm +14 -16
- package/ios/Layouts/Stack/ANNPreviewPush.h +7 -6
- package/ios/Layouts/Stack/ANNPreviewPush.mm +57 -5
- package/ios/Layouts/Stack/ANNStackAnimatingDelegate.h +11 -2
- package/ios/Layouts/Stack/ANNStackAnimatingDelegate.mm +14 -7
- package/ios/Layouts/Stack/ANNStackController.h +8 -0
- package/ios/Layouts/Stack/ANNStackController.mm +153 -11
- package/ios/Layouts/Stack/ANNSwipePopInteraction.h +26 -0
- package/ios/Layouts/Stack/ANNSwipePopInteraction.mm +185 -0
- package/ios/Layouts/Stack/InteractivePopGestureDelegate.mm +28 -4
- package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.h +12 -1
- package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.mm +23 -0
- package/ios/Layouts/Tabs/ANNBottomTabsController.mm +2 -1
- package/ios/Layouts/Tabs/ANNBottomTabsCustomRow.mm +8 -3
- package/ios/Layouts/Tabs/ANNBottomTabsPresenter.h +4 -0
- package/ios/Layouts/Tabs/ANNBottomTabsPresenter.mm +123 -36
- package/ios/Layouts/Tabs/ANNTabsDesign.h +6 -5
- package/ios/Layouts/Tabs/ANNTabsDesign.mm +9 -1
- package/ios/Layouts/Tabs/UITabBar+utils.h +5 -5
- package/ios/Layouts/Tabs/UITabBar+utils.mm +32 -13
- package/ios/Options/ANNAnimationOptions.h +2 -1
- package/ios/Options/ANNAnimationOptions.mm +1 -1
- package/ios/Options/ANNBottomTabsOptions.h +2 -0
- package/ios/Options/ANNBottomTabsOptions.mm +1 -0
- package/ios/Options/ANNOptions.h +25 -0
- package/ios/Options/ANNOptions.mm +157 -1
- package/ios/Options/ANNOptionsReader.mm +108 -0
- package/ios/Options/ANNStackPopAnimationOptions.h +13 -0
- package/ios/Options/ANNStackPopAnimationOptions.mm +11 -0
- package/ios/Options/Params/ANNParam.h +15 -0
- package/ios/Options/Params/ANNParam.mm +61 -0
- package/ios/Options/Params/Color.h +3 -0
- package/ios/Options/Params/Color.mm +21 -0
- package/ios/Options/Params/ColorParser.h +4 -3
- package/ios/Options/Params/ColorParser.mm +22 -4
- package/ios/Options/Params/Image.h +4 -0
- package/ios/Options/Params/Image.mm +20 -0
- package/ios/React/ANNReactView.mm +6 -25
- package/ios/React/ANNSafeAreaViewComponentView.mm +26 -15
- package/ios/React/ANNSurfaceHostingView.h +14 -0
- package/ios/React/ANNSurfaceHostingView.mm +144 -1
- package/ios/React/Slots/ANNSlotScreenView.mm +8 -2
- package/ios/TopBar/ANNBackButtonPresenter.mm +6 -5
- package/ios/TopBar/ANNBarAppearance.h +2 -1
- package/ios/TopBar/ANNBarAppearance.mm +111 -30
- package/ios/TopBar/ANNBarBackgroundComponent.mm +16 -0
- package/ios/TopBar/ANNBarButtonComponentView.h +4 -4
- package/ios/TopBar/ANNBarButtonComponentView.mm +1 -1
- package/ios/TopBar/ANNBarButtons.h +5 -3
- package/ios/TopBar/ANNBarButtons.mm +186 -17
- package/ios/TopBar/ANNLargeTitlePresenter.mm +24 -4
- package/ios/TopBar/ANNMainList.h +3 -0
- package/ios/TopBar/ANNMainList.mm +4 -0
- package/ios/TopBar/ANNScrollEdgeEffects.h +22 -6
- package/ios/TopBar/ANNScrollEdgeEffects.mm +123 -16
- package/ios/TopBar/ANNSearchPresenter.mm +2 -2
- package/ios/TopBar/ANNSearchResultsViewController.mm +5 -5
- package/ios/TopBar/ANNTopBarPresenter.h +3 -2
- package/ios/TopBar/ANNTopBarPresenter.mm +95 -22
- package/ios/TurboModules/ANNTurboModule.mm +66 -16
- package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.cpp +20 -0
- package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.h +5 -14
- package/lib/module/ARCHITECTURE.md +17 -7
- package/lib/module/adapters/NativeANNTurboModule.js.map +1 -1
- package/lib/module/api/app/AppRegistry.js +14 -2
- package/lib/module/api/app/AppRegistry.js.map +1 -1
- package/lib/module/api/app/createNavigation.js +188 -66
- package/lib/module/api/app/createNavigation.js.map +1 -1
- package/lib/module/api/events/navigationEvents.js +6 -2
- package/lib/module/api/events/navigationEvents.js.map +1 -1
- package/lib/module/api/hooks/useSafeAreaInsets.js +4 -3
- package/lib/module/api/hooks/useSafeAreaInsets.js.map +1 -1
- package/lib/module/api/linking/linking.js +11 -0
- package/lib/module/api/linking/linking.js.map +1 -1
- package/lib/module/api/options/OptionsChain.js +2 -2
- package/lib/module/api/screens/defineScreen.js +45 -3
- package/lib/module/api/screens/defineScreen.js.map +1 -1
- package/lib/module/api/screens/nativeScreens.js +31 -6
- package/lib/module/api/screens/nativeScreens.js.map +1 -1
- package/lib/module/api/screens/registerScreens.js +172 -35
- package/lib/module/api/screens/registerScreens.js.map +1 -1
- package/lib/module/api/theme/theme.js +5 -0
- package/lib/module/api/theme/theme.js.map +1 -1
- package/lib/module/engine/commands.js +42 -2
- package/lib/module/engine/commands.js.map +1 -1
- package/lib/module/engine/layout.js +7 -2
- package/lib/module/engine/layout.js.map +1 -1
- package/lib/module/engine/nativeScreens.js +9 -0
- package/lib/module/engine/nativeScreens.js.map +1 -1
- package/lib/module/engine/options.js +5 -4
- package/lib/module/engine/options.js.map +1 -1
- package/lib/module/engine/optionsChange.js +102 -0
- package/lib/module/engine/optionsChange.js.map +1 -0
- package/lib/module/engine/refresh.js +85 -0
- package/lib/module/engine/refresh.js.map +1 -0
- package/lib/module/engine/rememberedOptions.js +60 -0
- package/lib/module/engine/rememberedOptions.js.map +1 -1
- package/lib/module/engine/screens.js +55 -4
- package/lib/module/engine/screens.js.map +1 -1
- package/lib/typescript/adapters/NativeANNTurboModule.d.ts +7 -0
- package/lib/typescript/adapters/NativeANNTurboModule.d.ts.map +1 -1
- package/lib/typescript/api/app/AppRegistry.d.ts.map +1 -1
- package/lib/typescript/api/app/createNavigation.d.ts +8 -3
- package/lib/typescript/api/app/createNavigation.d.ts.map +1 -1
- package/lib/typescript/api/events/navigationEvents.d.ts +2 -2
- package/lib/typescript/api/events/navigationEvents.d.ts.map +1 -1
- package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts +4 -3
- package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts.map +1 -1
- package/lib/typescript/api/index.d.ts +1 -1
- package/lib/typescript/api/index.d.ts.map +1 -1
- package/lib/typescript/api/linking/linking.d.ts +8 -0
- package/lib/typescript/api/linking/linking.d.ts.map +1 -1
- package/lib/typescript/api/options/OptionsChain.d.ts +2 -2
- package/lib/typescript/api/screens/defineScreen.d.ts +23 -4
- package/lib/typescript/api/screens/defineScreen.d.ts.map +1 -1
- package/lib/typescript/api/screens/nativeScreens.d.ts +8 -1
- package/lib/typescript/api/screens/nativeScreens.d.ts.map +1 -1
- package/lib/typescript/api/screens/registerScreens.d.ts.map +1 -1
- package/lib/typescript/api/theme/theme.d.ts +2 -0
- package/lib/typescript/api/theme/theme.d.ts.map +1 -1
- package/lib/typescript/engine/commands.d.ts +5 -0
- package/lib/typescript/engine/commands.d.ts.map +1 -1
- package/lib/typescript/engine/layout.d.ts.map +1 -1
- package/lib/typescript/engine/nativeScreens.d.ts +5 -0
- package/lib/typescript/engine/nativeScreens.d.ts.map +1 -1
- package/lib/typescript/engine/optionsChange.d.ts +28 -0
- package/lib/typescript/engine/optionsChange.d.ts.map +1 -0
- package/lib/typescript/engine/refresh.d.ts +35 -0
- package/lib/typescript/engine/refresh.d.ts.map +1 -0
- package/lib/typescript/engine/rememberedOptions.d.ts +13 -0
- package/lib/typescript/engine/rememberedOptions.d.ts.map +1 -1
- package/lib/typescript/engine/screens.d.ts +27 -6
- package/lib/typescript/engine/screens.d.ts.map +1 -1
- package/lib/typescript/interfaces/ComponentEvents.d.ts +2 -2
- package/lib/typescript/interfaces/options/animations.d.ts +44 -14
- package/lib/typescript/interfaces/options/animations.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/bottomTabs.d.ts +19 -6
- package/lib/typescript/interfaces/options/bottomTabs.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/buttons.d.ts +10 -10
- package/lib/typescript/interfaces/options/modals.d.ts +6 -7
- package/lib/typescript/interfaces/options/modals.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/stack.d.ts +8 -3
- package/lib/typescript/interfaces/options/stack.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/system.d.ts +8 -5
- package/lib/typescript/interfaces/options/system.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/toolbar.d.ts +2 -2
- package/lib/typescript/interfaces/options/topBar.d.ts +46 -29
- package/lib/typescript/interfaces/options/topBar.d.ts.map +1 -1
- package/metro/acceptPlugin.js +57 -0
- package/metro/babelTransformer.js +45 -0
- package/metro/index.js +36 -0
- package/package.json +3 -1
- package/src/ARCHITECTURE.md +17 -7
- package/src/adapters/NativeANNTurboModule.ts +7 -0
- package/src/api/app/AppRegistry.ts +16 -2
- package/src/api/app/createNavigation.ts +201 -69
- package/src/api/events/navigationEvents.ts +9 -3
- package/src/api/hooks/useSafeAreaInsets.ts +4 -3
- package/src/api/index.ts +1 -0
- package/src/api/linking/linking.ts +22 -1
- package/src/api/options/OptionsChain.ts +2 -2
- package/src/api/screens/defineScreen.ts +49 -5
- package/src/api/screens/nativeScreens.ts +40 -4
- package/src/api/screens/registerScreens.tsx +170 -42
- package/src/api/theme/theme.ts +5 -0
- package/src/engine/commands.ts +51 -6
- package/src/engine/layout.ts +11 -2
- package/src/engine/nativeScreens.ts +10 -1
- package/src/engine/options.ts +6 -8
- package/src/engine/optionsChange.ts +107 -0
- package/src/engine/refresh.ts +97 -0
- package/src/engine/rememberedOptions.ts +70 -0
- package/src/engine/screens.tsx +53 -8
- package/src/interfaces/ComponentEvents.ts +2 -2
- package/src/interfaces/options/animations.ts +44 -14
- package/src/interfaces/options/bottomTabs.ts +19 -6
- package/src/interfaces/options/buttons.ts +10 -10
- package/src/interfaces/options/modals.ts +6 -7
- package/src/interfaces/options/stack.ts +8 -3
- package/src/interfaces/options/system.ts +8 -5
- package/src/interfaces/options/toolbar.ts +2 -2
- package/src/interfaces/options/topBar.ts +46 -29
- package/android/src/main/java/dev/apexnative/navigation/react/ArrangementStates.kt +0 -42
- package/android/src/main/java/dev/apexnative/navigation/react/ScreenInsets.kt +0 -70
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowPlacer.kt +0 -223
- package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStub.kt +0 -31
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMatrixAnimator.kt +0 -136
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PlainViewAnimator.kt +0 -86
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PropertyAnimatorCreator.kt +0 -33
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ReactImageAnimator.kt +0 -64
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextChangeAnimator.kt +0 -177
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewChangeAnimator.kt +0 -137
- package/ios/Layouts/Screen/ANNScreenInsets.h +0 -30
- package/ios/Layouts/Screen/ANNScreenInsets.mm +0 -70
|
@@ -15,6 +15,7 @@ import dev.apexnative.navigation.viewcontrollers.component.ComponentViewControll
|
|
|
15
15
|
import dev.apexnative.navigation.viewcontrollers.externalcomponent.ExternalComponentViewController
|
|
16
16
|
import dev.apexnative.navigation.viewcontrollers.stack.StackDisplay.Motion
|
|
17
17
|
import dev.apexnative.navigation.viewcontrollers.viewcontroller.ViewController
|
|
18
|
+
import dev.apexnative.navigation.views.animations.AnimationLayer
|
|
18
19
|
import dev.apexnative.navigation.views.animations.AnimationRules
|
|
19
20
|
import dev.apexnative.navigation.views.animations.SideAnimator
|
|
20
21
|
import dev.apexnative.navigation.views.animations.SystemTransition
|
|
@@ -149,14 +150,17 @@ internal class StackViews(private val stack: StackController) : StackDisplay {
|
|
|
149
150
|
}
|
|
150
151
|
}
|
|
151
152
|
|
|
152
|
-
// The elements
|
|
153
|
-
// without a duration takes the screen's fade: its own single `alpha`,
|
|
153
|
+
// The elements play in their screens and the pairs' copies fly in a layer over them, all done as the screen's
|
|
154
|
+
// animator ends or stops. A shared element without a duration takes the screen's fade: its own single `alpha`,
|
|
155
|
+
// else 300 ms.
|
|
154
156
|
override fun animateCustom(screen: ViewController<*>, custom: StackDisplay.Custom, done: () -> Unit) {
|
|
155
157
|
stop(screen)
|
|
156
158
|
val view = screen.peekView() ?: return done()
|
|
157
159
|
custom.alpha?.let { view.alpha = it }
|
|
158
160
|
val own = custom.side?.let { SideAnimator.build(view, it, SideAnimator.Base(alpha = custom.alpha)) }
|
|
159
161
|
val fade = if (own == null) StackTransitions.fade(view, custom.fade) else null
|
|
162
|
+
// A fade of the whole screen draws it through a hardware layer, as the default transition does ([dress]).
|
|
163
|
+
for (animator in listOfNotNull(own, fade)) AnimationLayer.during(view, animator)
|
|
160
164
|
val elements = custom.elements?.let { elements ->
|
|
161
165
|
val layout = layout ?: return@let null
|
|
162
166
|
val fadeLength = custom.side?.takeIf(AnimationRules::isSingleAlpha)?.let(AnimationRules::lengthOf)
|
|
@@ -196,7 +200,7 @@ internal class StackViews(private val stack: StackController) : StackDisplay {
|
|
|
196
200
|
|
|
197
201
|
/**
|
|
198
202
|
* Starts the preview of a back gesture over [top], [target] under it (`BackPreview`): none without the stack's view
|
|
199
|
-
* or a window. [onReveal] shows [target]
|
|
203
|
+
* or a window. [onReveal] shows [target] with its bar and its FAB as the preview's picture is there.
|
|
200
204
|
*/
|
|
201
205
|
fun startBackPreview(
|
|
202
206
|
top: ViewController<*>,
|
|
@@ -211,7 +215,9 @@ internal class StackViews(private val stack: StackController) : StackDisplay {
|
|
|
211
215
|
val window = stack.activity.window ?: return null
|
|
212
216
|
val topView = top.peekView() ?: return null
|
|
213
217
|
val targetView = target.peekView() ?: return null
|
|
214
|
-
val started = BackPreview(layout, topView, targetView, fromLeft, touchY, bottomRoom, onReveal)
|
|
218
|
+
val started = BackPreview(layout, topView, targetView, fromLeft, touchY, bottomRoom, onReveal) {
|
|
219
|
+
stack.fab.shownView
|
|
220
|
+
}
|
|
215
221
|
preview = started
|
|
216
222
|
previewScreens = top to target
|
|
217
223
|
started.start(window)
|
package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabMotion.kt
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
package dev.apexnative.navigation.viewcontrollers.stack.fab
|
|
2
|
+
|
|
3
|
+
import dev.apexnative.navigation.viewcontrollers.stack.StackDisplay.BarMotion
|
|
4
|
+
import dev.apexnative.navigation.views.animations.FadeThrough
|
|
5
|
+
import dev.apexnative.navigation.views.animations.SystemTransition
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* How a stack's FAB goes with a change of its screen on top, as the values alone: the new top's FAB arrives with its
|
|
9
|
+
* screen and a copy of the old one leaves with the screen it belonged to, from the start of the transition. A FAB with
|
|
10
|
+
* the same id stays where it is. The stack plays them on its views (`FabPresenter`).
|
|
11
|
+
*/
|
|
12
|
+
internal object FabMotion {
|
|
13
|
+
/** How the stack's transition goes, as its queue tells it (`StackQueue.Host.fabTransition`). */
|
|
14
|
+
enum class Move {
|
|
15
|
+
/** The system's push: each FAB rides with its screen along the line, as the tab bar does. */
|
|
16
|
+
WithPush,
|
|
17
|
+
|
|
18
|
+
/** The system's pop: the same, the other way. */
|
|
19
|
+
WithPop,
|
|
20
|
+
|
|
21
|
+
/** The fade through of a `setStackRoot`: the old one fades out first, the new one fades in and grows. */
|
|
22
|
+
FadeThrough,
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* A transition of the screens' own (`content`, elements): Material's swap at its start, the old one shrinking
|
|
26
|
+
* away, the new one growing from 60 %.
|
|
27
|
+
*/
|
|
28
|
+
Swap,
|
|
29
|
+
|
|
30
|
+
/** No animation: the new top's FAB is there at once. */
|
|
31
|
+
AtOnce,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** The curve a ride's move and scale take; its alpha changes on a straight line. */
|
|
35
|
+
enum class Curve { System, FadeThrough, Material }
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* A FAB's ride: along the x axis in dp, mirrored right to left; its scale on [curve] over [duration]; its alpha after
|
|
39
|
+
* a hold of [alphaDelay] over [alphaDuration], in ms.
|
|
40
|
+
*/
|
|
41
|
+
data class Ride(
|
|
42
|
+
val fromX: Float,
|
|
43
|
+
val toX: Float,
|
|
44
|
+
val fromAlpha: Float,
|
|
45
|
+
val toAlpha: Float,
|
|
46
|
+
val fromScale: Float,
|
|
47
|
+
val toScale: Float,
|
|
48
|
+
val alphaDelay: Long,
|
|
49
|
+
val alphaDuration: Long,
|
|
50
|
+
val duration: Long,
|
|
51
|
+
val curve: Curve,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
/** How long Material's swap takes, as the FAB shrinks or grows. */
|
|
55
|
+
const val SWAP_MILLIS = 200L
|
|
56
|
+
|
|
57
|
+
/** Where Material's swap grows the new FAB from. */
|
|
58
|
+
const val GROW_FROM = 0.6f
|
|
59
|
+
|
|
60
|
+
private const val FADE_THROUGH_SCALE = 0.92f
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The move of the FAB with a change of the current child: none when the change comes at once or the new top shows
|
|
64
|
+
* already ([shown]: a back gesture's preview showed it); Material's swap with an animation of the screens' own
|
|
65
|
+
* ([own]); else the default transition's [row], as the bar's row goes.
|
|
66
|
+
*/
|
|
67
|
+
fun moveOf(animated: Boolean, own: Boolean, row: BarMotion, shown: Boolean): Move = when {
|
|
68
|
+
!animated || shown -> Move.AtOnce
|
|
69
|
+
own -> Move.Swap
|
|
70
|
+
row == BarMotion.Push -> Move.WithPush
|
|
71
|
+
row == BarMotion.Pop -> Move.WithPop
|
|
72
|
+
else -> Move.FadeThrough
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* The new top's FAB comes with its screen: a push brings it from +96 dp (−96 dp on a pop), transparent for the hold
|
|
77
|
+
* of the screen's fade, then fading in; the fade through fades it in after the old one went and grows it from 92 %;
|
|
78
|
+
* the swap grows it from 60 %. None at once.
|
|
79
|
+
*/
|
|
80
|
+
fun arrival(move: Move, rtl: Boolean): Ride? {
|
|
81
|
+
val distance = SystemTransition.DISTANCE_DP * if (rtl) -1 else 1
|
|
82
|
+
return when (move) {
|
|
83
|
+
Move.WithPush, Move.WithPop -> Ride(
|
|
84
|
+
fromX = if (move == Move.WithPush) distance else -distance,
|
|
85
|
+
toX = 0f,
|
|
86
|
+
fromAlpha = 0f,
|
|
87
|
+
toAlpha = 1f,
|
|
88
|
+
fromScale = 1f,
|
|
89
|
+
toScale = 1f,
|
|
90
|
+
alphaDelay = fadeDelay(move),
|
|
91
|
+
alphaDuration = SystemTransition.FADE_DURATION,
|
|
92
|
+
duration = SystemTransition.DURATION,
|
|
93
|
+
curve = Curve.System,
|
|
94
|
+
)
|
|
95
|
+
Move.FadeThrough -> Ride(
|
|
96
|
+
fromX = 0f,
|
|
97
|
+
toX = 0f,
|
|
98
|
+
fromAlpha = 0f,
|
|
99
|
+
toAlpha = 1f,
|
|
100
|
+
fromScale = FADE_THROUGH_SCALE,
|
|
101
|
+
toScale = 1f,
|
|
102
|
+
alphaDelay = fadeThroughOut(),
|
|
103
|
+
alphaDuration = FadeThrough.DURATION - fadeThroughOut(),
|
|
104
|
+
duration = FadeThrough.DURATION,
|
|
105
|
+
curve = Curve.FadeThrough,
|
|
106
|
+
)
|
|
107
|
+
Move.Swap -> Ride(0f, 0f, 1f, 1f, GROW_FROM, 1f, 0L, 0L, SWAP_MILLIS, Curve.Material)
|
|
108
|
+
Move.AtOnce -> null
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* The old top's FAB leaves with its screen, from where it is: a push takes it to −96 dp with the covered screen and
|
|
114
|
+
* fades it out as the new screen fades in over it; a pop takes it to +96 dp, fading with the leaving screen; the
|
|
115
|
+
* fade through fades it out in the first 35 %; the swap shrinks it to nothing. None at once.
|
|
116
|
+
*/
|
|
117
|
+
fun departure(move: Move, rtl: Boolean): Ride? {
|
|
118
|
+
val distance = SystemTransition.DISTANCE_DP * if (rtl) -1 else 1
|
|
119
|
+
return when (move) {
|
|
120
|
+
Move.WithPush, Move.WithPop -> Ride(
|
|
121
|
+
fromX = 0f,
|
|
122
|
+
toX = if (move == Move.WithPush) -distance else distance,
|
|
123
|
+
fromAlpha = 1f,
|
|
124
|
+
toAlpha = 0f,
|
|
125
|
+
fromScale = 1f,
|
|
126
|
+
toScale = 1f,
|
|
127
|
+
alphaDelay = fadeDelay(move),
|
|
128
|
+
alphaDuration = SystemTransition.FADE_DURATION,
|
|
129
|
+
duration = SystemTransition.DURATION,
|
|
130
|
+
curve = Curve.System,
|
|
131
|
+
)
|
|
132
|
+
Move.FadeThrough -> Ride(0f, 0f, 1f, 0f, 1f, 1f, 0L, fadeThroughOut(), fadeThroughOut(), Curve.FadeThrough)
|
|
133
|
+
Move.Swap -> Ride(0f, 0f, 1f, 1f, 1f, 0f, 0L, 0L, SWAP_MILLIS, Curve.Material)
|
|
134
|
+
Move.AtOnce -> null
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private fun fadeDelay(move: Move): Long =
|
|
139
|
+
if (move == Move.WithPush) SystemTransition.PUSH_FADE_DELAY else SystemTransition.POP_FADE_DELAY
|
|
140
|
+
|
|
141
|
+
private fun fadeThroughOut(): Long = (FadeThrough.DURATION * FadeThrough.OUT).toLong()
|
|
142
|
+
}
|
package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabPresenter.kt
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
package dev.apexnative.navigation.viewcontrollers.stack.fab
|
|
2
2
|
|
|
3
|
+
import android.animation.Animator
|
|
4
|
+
import android.animation.AnimatorListenerAdapter
|
|
5
|
+
import android.animation.AnimatorSet
|
|
6
|
+
import android.animation.ObjectAnimator
|
|
7
|
+
import android.animation.PropertyValuesHolder
|
|
3
8
|
import android.app.Activity
|
|
4
9
|
import android.view.Gravity
|
|
5
10
|
import android.view.View
|
|
6
11
|
import android.view.ViewGroup
|
|
12
|
+
import android.view.animation.AccelerateDecelerateInterpolator
|
|
13
|
+
import android.view.animation.LinearInterpolator
|
|
7
14
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
8
15
|
import androidx.core.view.WindowInsetsCompat
|
|
9
16
|
import dev.apexnative.navigation.options.FabOptions
|
|
@@ -11,16 +18,20 @@ import dev.apexnative.navigation.react.events.AppearanceDispatcher
|
|
|
11
18
|
import dev.apexnative.navigation.utils.TestIds
|
|
12
19
|
import dev.apexnative.navigation.viewcontrollers.viewcontroller.ScrollEventListener
|
|
13
20
|
import dev.apexnative.navigation.viewcontrollers.viewcontroller.ViewController
|
|
21
|
+
import dev.apexnative.navigation.views.animations.FadeThrough
|
|
22
|
+
import dev.apexnative.navigation.views.animations.SystemTransition
|
|
14
23
|
import dev.apexnative.navigation.views.stack.StackLayout
|
|
15
24
|
import dev.apexnative.navigation.views.stack.fab.Fab
|
|
25
|
+
import dev.apexnative.navigation.views.stack.fab.FabCopy
|
|
16
26
|
import dev.apexnative.navigation.views.stack.fab.FabMenu
|
|
17
27
|
|
|
18
28
|
/**
|
|
19
29
|
* The FAB of one stack (`fab.*`), over the module's `Fab` and `FabMenu`: one FAB or one menu at a time, from the
|
|
20
30
|
* resolved `fab` of the screen on top (its options over the stack's, its parents' and the defaults). It follows the top
|
|
21
|
-
*
|
|
22
|
-
* screen whose options showed it, an action with its own id. Its views are
|
|
23
|
-
* screens and the bar
|
|
31
|
+
* from the start of each transition, going with the screens by [FabMotion], and the merges of `fab` into it; a press
|
|
32
|
+
* sends `ANN.NavigationButtonPressed` with the screen whose options showed it, an action with its own id. Its views are
|
|
33
|
+
* children of the stack's view, over the screens and the bar; a FAB that leaves goes as a copy ([FabCopy]). Main
|
|
34
|
+
* thread only.
|
|
24
35
|
*/
|
|
25
36
|
internal class FabPresenter(
|
|
26
37
|
private val activity: Activity,
|
|
@@ -38,38 +49,75 @@ internal class FabPresenter(
|
|
|
38
49
|
var source: ViewController<*>? = null
|
|
39
50
|
private set
|
|
40
51
|
|
|
52
|
+
// The ride of the FAB that shows as it arrives; none at rest.
|
|
53
|
+
private var ride: Animator? = null
|
|
54
|
+
// The copies of the FABs that leave, each with its ride.
|
|
55
|
+
private val copies = LinkedHashMap<FabCopy, Animator>()
|
|
56
|
+
|
|
57
|
+
// The top's FAB while a back gesture's preview shows the screen under the top with its own: out of the stack, as
|
|
58
|
+
// it was (hidden by the scroll, say).
|
|
59
|
+
private class Aside(
|
|
60
|
+
val fab: Fab?,
|
|
61
|
+
val menu: FabMenu?,
|
|
62
|
+
val shownId: String?,
|
|
63
|
+
var source: ViewController<*>?,
|
|
64
|
+
val alignStart: Boolean,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
private var aside: Aside? = null
|
|
68
|
+
|
|
41
69
|
private val view: View?
|
|
42
70
|
get() = menu ?: fab
|
|
43
71
|
|
|
72
|
+
/** The view of the FAB or of its menu that shows; none. */
|
|
73
|
+
val shownView: View?
|
|
74
|
+
get() = view
|
|
75
|
+
|
|
44
76
|
/**
|
|
45
|
-
* The screen on top became [source], with its resolved [options]
|
|
46
|
-
* it
|
|
47
|
-
*
|
|
77
|
+
* The screen on top became [source], with its resolved [options], in a transition that goes by [move]: the same id
|
|
78
|
+
* updates the FAB that shows, where it stays as it is, another id replaces it, none takes it away — the new FAB
|
|
79
|
+
* arrives and a copy of the old one leaves by [move]; the scroll of [scroll] hides it with `hideOnScroll`. An open
|
|
80
|
+
* menu closes. The copies of an older transition go, and with [FabMotion.Move.AtOnce] a FAB still riding comes to
|
|
81
|
+
* rest. Nothing when [source] already shows it.
|
|
48
82
|
*/
|
|
49
|
-
fun showFor(
|
|
83
|
+
fun showFor(
|
|
84
|
+
layout: StackLayout,
|
|
85
|
+
source: ViewController<*>?,
|
|
86
|
+
options: FabOptions,
|
|
87
|
+
scroll: ScrollEventListener?,
|
|
88
|
+
move: FabMotion.Move = FabMotion.Move.Swap,
|
|
89
|
+
) {
|
|
90
|
+
// At once, what still moves comes to rest, also when the top stays (a failed push).
|
|
91
|
+
if (move == FabMotion.Move.AtOnce) {
|
|
92
|
+
dropCopies()
|
|
93
|
+
stopRide(rest = true)
|
|
94
|
+
}
|
|
50
95
|
if (source === this.source && this.layout === layout) return
|
|
51
96
|
this.layout = layout
|
|
52
|
-
|
|
97
|
+
dropCopies()
|
|
53
98
|
this.source = source
|
|
54
99
|
when (FabPlan.step(shownId, menu != null, options)) {
|
|
55
100
|
FabPlan.Step.None -> Unit
|
|
56
|
-
FabPlan.Step.Remove ->
|
|
57
|
-
FabPlan.Step.Create ->
|
|
101
|
+
FabPlan.Step.Remove -> leave(layout, move)
|
|
102
|
+
FabPlan.Step.Create -> {
|
|
103
|
+
create(layout, options, scroll)
|
|
104
|
+
arrive(move)
|
|
105
|
+
}
|
|
58
106
|
FabPlan.Step.Replace -> {
|
|
59
|
-
|
|
107
|
+
leave(layout, move)
|
|
60
108
|
create(layout, options, scroll)
|
|
109
|
+
arrive(move)
|
|
61
110
|
}
|
|
62
111
|
FabPlan.Step.Update -> {
|
|
112
|
+
disableCollapse()
|
|
113
|
+
menu?.close()
|
|
63
114
|
apply(options, scroll)
|
|
64
115
|
// A new top whose options don't hide it shows it, even where the screen before hid it.
|
|
65
116
|
if (!options.visible.isFalse) {
|
|
66
117
|
fab?.show()
|
|
67
118
|
menu?.show()
|
|
68
119
|
}
|
|
69
|
-
view?.
|
|
70
|
-
it.bringToFront()
|
|
71
|
-
grow(it)
|
|
72
|
-
}
|
|
120
|
+
view?.bringToFront()
|
|
73
121
|
}
|
|
74
122
|
}
|
|
75
123
|
}
|
|
@@ -83,11 +131,15 @@ internal class FabPresenter(
|
|
|
83
131
|
this.source = source
|
|
84
132
|
when (FabPlan.step(shownId, menu != null, options)) {
|
|
85
133
|
FabPlan.Step.None -> Unit
|
|
86
|
-
FabPlan.Step.Remove ->
|
|
87
|
-
FabPlan.Step.Create ->
|
|
134
|
+
FabPlan.Step.Remove -> leave(layout, FabMotion.Move.Swap)
|
|
135
|
+
FabPlan.Step.Create -> {
|
|
136
|
+
create(layout, options, scroll)
|
|
137
|
+
arrive(FabMotion.Move.Swap)
|
|
138
|
+
}
|
|
88
139
|
FabPlan.Step.Replace -> {
|
|
89
|
-
|
|
140
|
+
leave(layout, FabMotion.Move.Swap)
|
|
90
141
|
create(layout, options, scroll)
|
|
142
|
+
arrive(FabMotion.Move.Swap)
|
|
91
143
|
}
|
|
92
144
|
FabPlan.Step.Update -> apply(options, scroll)
|
|
93
145
|
}
|
|
@@ -130,13 +182,57 @@ internal class FabPresenter(
|
|
|
130
182
|
view.layoutParams = params
|
|
131
183
|
}
|
|
132
184
|
|
|
185
|
+
/**
|
|
186
|
+
* A back gesture's preview shows the screen under the top: the FAB that shows goes aside, out of the stack but as it
|
|
187
|
+
* is, its menu closing, until [bringBack] or [dropAside]; the screen's own FAB shows next ([showFor]).
|
|
188
|
+
*/
|
|
189
|
+
fun setAside() {
|
|
190
|
+
if (aside != null) return
|
|
191
|
+
dropCopies()
|
|
192
|
+
stopRide(rest = true)
|
|
193
|
+
menu?.close()
|
|
194
|
+
view?.let { (it.parent as? ViewGroup)?.removeView(it) }
|
|
195
|
+
aside = Aside(fab, menu, shownId, source, alignStart)
|
|
196
|
+
fab = null
|
|
197
|
+
menu = null
|
|
198
|
+
shownId = null
|
|
199
|
+
source = null
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** The gesture was cancelled: the FAB the preview showed goes, and the one set aside is back as it was. */
|
|
203
|
+
fun bringBack() {
|
|
204
|
+
val kept = aside ?: return
|
|
205
|
+
aside = null
|
|
206
|
+
val layout = layout ?: return discard(kept)
|
|
207
|
+
leave(layout, FabMotion.Move.AtOnce)
|
|
208
|
+
fab = kept.fab
|
|
209
|
+
menu = kept.menu
|
|
210
|
+
shownId = kept.shownId
|
|
211
|
+
source = kept.source
|
|
212
|
+
alignStart = kept.alignStart
|
|
213
|
+
view?.let { layout.addOverAll(it, it.layoutParams as? CoordinatorLayout.LayoutParams ?: params()) }
|
|
214
|
+
place()
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** The gesture was released: the FAB set aside goes with the top that leaves. */
|
|
218
|
+
fun dropAside() {
|
|
219
|
+
val kept = aside ?: return
|
|
220
|
+
aside = null
|
|
221
|
+
discard(kept)
|
|
222
|
+
}
|
|
223
|
+
|
|
133
224
|
/** [node] was destroyed: a FAB it showed sends nothing more. */
|
|
134
225
|
fun forget(node: ViewController<*>) {
|
|
135
226
|
if (source === node) source = null
|
|
227
|
+
aside?.let { if (it.source === node) it.source = null }
|
|
136
228
|
}
|
|
137
229
|
|
|
138
|
-
/** The stack goes: the FAB and its menu go at once, the scrim first. */
|
|
230
|
+
/** The stack goes: the FAB and its menu go at once, the scrim first, and the copies that leave. */
|
|
139
231
|
fun destroy() {
|
|
232
|
+
aside?.let(::discard)
|
|
233
|
+
aside = null
|
|
234
|
+
dropCopies()
|
|
235
|
+
stopRide(rest = false)
|
|
140
236
|
disableCollapse()
|
|
141
237
|
menu?.let {
|
|
142
238
|
it.removeScrim()
|
|
@@ -153,7 +249,7 @@ internal class FabPresenter(
|
|
|
153
249
|
private fun create(layout: StackLayout, options: FabOptions, scroll: ScrollEventListener?) {
|
|
154
250
|
val id = FabPlan.idOf(options) ?: return
|
|
155
251
|
shownId = id
|
|
156
|
-
val params =
|
|
252
|
+
val params = params()
|
|
157
253
|
if (FabPlan.isMenu(options)) {
|
|
158
254
|
val menu = FabMenu(activity, id)
|
|
159
255
|
this.menu = menu
|
|
@@ -164,7 +260,6 @@ internal class FabPresenter(
|
|
|
164
260
|
layout.addOverAll(fab, params)
|
|
165
261
|
}
|
|
166
262
|
apply(options, scroll)
|
|
167
|
-
view?.let(::grow)
|
|
168
263
|
}
|
|
169
264
|
|
|
170
265
|
// Every option of the FAB that shows; the collapse before the visibility, which `disableCollapse` would undo.
|
|
@@ -235,43 +330,120 @@ internal class FabPresenter(
|
|
|
235
330
|
menu?.disableCollapse()
|
|
236
331
|
}
|
|
237
332
|
|
|
238
|
-
// The FAB that shows goes: a
|
|
239
|
-
|
|
333
|
+
// The FAB that shows goes with its screen: a copy of it leaves by [move] while the button, or the menu, goes from the
|
|
334
|
+
// stack at once; an open menu closes, its scrim fading out by itself. At once nothing leaves, the scrim neither.
|
|
335
|
+
private fun leave(layout: StackLayout, move: FabMotion.Move) {
|
|
336
|
+
val view = view ?: return
|
|
337
|
+
val departure = FabMotion.departure(move, isRtl(layout))
|
|
338
|
+
val copy = departure?.let { FabCopy.of((view as? FabMenu)?.main ?: view, view, layout) }
|
|
339
|
+
stopRide(rest = false)
|
|
340
|
+
disableCollapse()
|
|
240
341
|
menu?.let {
|
|
241
|
-
it.removeScrim()
|
|
342
|
+
if (departure != null) it.closeToLeave() else it.removeScrim()
|
|
242
343
|
(it.parent as? ViewGroup)?.removeView(it)
|
|
243
344
|
}
|
|
244
|
-
fab?.let {
|
|
245
|
-
fab.animate().cancel()
|
|
246
|
-
if (!fab.isAttachedToWindow) {
|
|
247
|
-
(fab.parent as? ViewGroup)?.removeView(fab)
|
|
248
|
-
} else {
|
|
249
|
-
fab.animate().scaleX(0f).scaleY(0f).setDuration(ANIMATION_MILLIS)
|
|
250
|
-
.withEndAction { (fab.parent as? ViewGroup)?.removeView(fab) }.start()
|
|
251
|
-
}
|
|
252
|
-
}
|
|
345
|
+
fab?.let { (it.parent as? ViewGroup)?.removeView(it) }
|
|
253
346
|
menu = null
|
|
254
347
|
fab = null
|
|
255
348
|
shownId = null
|
|
349
|
+
if (copy == null) return
|
|
350
|
+
copies[copy] = play(copy, departure, fromCurrent = true) { copies.remove(copy)?.let { removeCopy(copy) } }
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// The new FAB arrives with its screen by [move]; one its options hide (`visible: false`) has nothing to show.
|
|
354
|
+
private fun arrive(move: FabMotion.Move) {
|
|
355
|
+
val view = view ?: return
|
|
356
|
+
if (((view as? FabMenu)?.main ?: view).visibility != View.VISIBLE) return
|
|
357
|
+
val arrival = FabMotion.arrival(move, layout?.let(::isRtl) ?: false) ?: return
|
|
358
|
+
ride = play(view, arrival, fromCurrent = false) { animator -> if (ride === animator) ride = null }
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// A ride stops where it is; [rest]: the FAB is in its place again, opaque and whole.
|
|
362
|
+
private fun stopRide(rest: Boolean) {
|
|
363
|
+
val running = ride ?: return
|
|
364
|
+
ride = null
|
|
365
|
+
running.cancel()
|
|
366
|
+
if (!rest) return
|
|
367
|
+
view?.apply {
|
|
368
|
+
translationX = 0f
|
|
369
|
+
alpha = 1f
|
|
370
|
+
scaleX = 1f
|
|
371
|
+
scaleY = 1f
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// The copies of an older transition go at once.
|
|
376
|
+
private fun dropCopies() {
|
|
377
|
+
if (copies.isEmpty()) return
|
|
378
|
+
val dropped = copies.toList()
|
|
379
|
+
copies.clear()
|
|
380
|
+
dropped.forEach { (copy, animator) ->
|
|
381
|
+
animator.cancel()
|
|
382
|
+
removeCopy(copy)
|
|
383
|
+
}
|
|
256
384
|
}
|
|
257
385
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
val target = (view as? FabMenu)?.main ?: view
|
|
261
|
-
target.animate().cancel()
|
|
262
|
-
target.scaleX = GROW_FROM
|
|
263
|
-
target.scaleY = GROW_FROM
|
|
264
|
-
target.animate().scaleX(1f).scaleY(1f).setDuration(ANIMATION_MILLIS).start()
|
|
386
|
+
private fun removeCopy(copy: FabCopy) {
|
|
387
|
+
(copy.parent as? ViewGroup)?.removeView(copy)
|
|
265
388
|
}
|
|
266
389
|
|
|
390
|
+
// Plays [ride] on [view], from its start values or [fromCurrent] from where the view is; [end] at its end or stop.
|
|
391
|
+
private fun play(view: View, ride: FabMotion.Ride, fromCurrent: Boolean, end: (Animator) -> Unit): Animator {
|
|
392
|
+
val density = activity.resources.displayMetrics.density
|
|
393
|
+
if (!fromCurrent) {
|
|
394
|
+
view.translationX = ride.fromX * density
|
|
395
|
+
view.alpha = ride.fromAlpha
|
|
396
|
+
view.scaleX = ride.fromScale
|
|
397
|
+
view.scaleY = ride.fromScale
|
|
398
|
+
}
|
|
399
|
+
val move = ObjectAnimator.ofPropertyValuesHolder(
|
|
400
|
+
view,
|
|
401
|
+
PropertyValuesHolder.ofFloat(View.TRANSLATION_X, ride.toX * density),
|
|
402
|
+
PropertyValuesHolder.ofFloat(View.SCALE_X, ride.toScale),
|
|
403
|
+
PropertyValuesHolder.ofFloat(View.SCALE_Y, ride.toScale),
|
|
404
|
+
).apply {
|
|
405
|
+
duration = ride.duration
|
|
406
|
+
interpolator = when (ride.curve) {
|
|
407
|
+
FabMotion.Curve.System -> SystemTransition.CURVE
|
|
408
|
+
FabMotion.Curve.FadeThrough -> FadeThrough.CURVE
|
|
409
|
+
FabMotion.Curve.Material -> AccelerateDecelerateInterpolator()
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
val animator = AnimatorSet()
|
|
413
|
+
if (ride.alphaDuration > 0) {
|
|
414
|
+
val fade = ObjectAnimator.ofFloat(view, View.ALPHA, ride.toAlpha).apply {
|
|
415
|
+
startDelay = ride.alphaDelay
|
|
416
|
+
duration = ride.alphaDuration
|
|
417
|
+
interpolator = LinearInterpolator()
|
|
418
|
+
}
|
|
419
|
+
animator.playTogether(move, fade)
|
|
420
|
+
} else {
|
|
421
|
+
animator.play(move)
|
|
422
|
+
}
|
|
423
|
+
animator.addListener(object : AnimatorListenerAdapter() {
|
|
424
|
+
override fun onAnimationEnd(animation: Animator) = end(animation)
|
|
425
|
+
})
|
|
426
|
+
animator.start()
|
|
427
|
+
return animator
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// A FAB set aside that won't come back: it follows no scroll, its scrim goes.
|
|
431
|
+
private fun discard(kept: Aside) {
|
|
432
|
+
kept.fab?.disableCollapse()
|
|
433
|
+
kept.menu?.disableCollapse()
|
|
434
|
+
kept.menu?.removeScrim()
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
private fun params() = CoordinatorLayout.LayoutParams(WRAP, WRAP)
|
|
438
|
+
|
|
439
|
+
private fun isRtl(layout: StackLayout): Boolean = layout.layoutDirection == View.LAYOUT_DIRECTION_RTL
|
|
440
|
+
|
|
267
441
|
companion object {
|
|
268
442
|
private const val WRAP = ViewGroup.LayoutParams.WRAP_CONTENT
|
|
269
|
-
private const val ANIMATION_MILLIS = 200L
|
|
270
|
-
private const val GROW_FROM = 0.6f
|
|
271
443
|
|
|
272
444
|
/**
|
|
273
445
|
* A press on the FAB, or on an action of its menu, of [source] (EVT-NavigationButtonPressed): nothing once
|
|
274
|
-
* [source] is destroyed
|
|
446
|
+
* [source] is destroyed.
|
|
275
447
|
*/
|
|
276
448
|
fun press(source: ViewController<*>?, buttonId: String) {
|
|
277
449
|
if (source == null || source.isDestroyed) return
|
|
@@ -3,8 +3,6 @@ package dev.apexnative.navigation.viewcontrollers.stack.search
|
|
|
3
3
|
import android.app.Activity
|
|
4
4
|
import android.content.Context
|
|
5
5
|
import android.graphics.drawable.Drawable
|
|
6
|
-
import android.view.Menu
|
|
7
|
-
import android.view.MenuItem
|
|
8
6
|
import android.view.View
|
|
9
7
|
import android.view.ViewGroup
|
|
10
8
|
import androidx.appcompat.R as AppCompatR
|
|
@@ -15,12 +13,14 @@ import androidx.core.view.WindowInsetsCompat
|
|
|
15
13
|
import dev.apexnative.navigation.options.SearchBarOptions
|
|
16
14
|
import dev.apexnative.navigation.options.params.ThemeColour
|
|
17
15
|
import dev.apexnative.navigation.react.events.EventEmitter
|
|
16
|
+
import dev.apexnative.navigation.utils.TestIds
|
|
18
17
|
import dev.apexnative.navigation.utils.dp
|
|
19
18
|
import dev.apexnative.navigation.viewcontrollers.parent.OptionsScreen
|
|
20
19
|
import dev.apexnative.navigation.viewcontrollers.viewcontroller.ViewController
|
|
21
20
|
import dev.apexnative.navigation.views.stack.topbar.TopBar
|
|
22
21
|
import dev.apexnative.navigation.views.stack.topbar.TopBarDefaults
|
|
23
22
|
import dev.apexnative.navigation.views.stack.topbar.search.SearchStyle
|
|
23
|
+
import dev.apexnative.navigation.views.stack.topbar.titlebar.BarButtonView
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* The search of the screens of a stack (`topBar.searchBar`): each screen has its own while it is in the stack, and the
|
|
@@ -38,6 +38,7 @@ class StackSearchPresenter(
|
|
|
38
38
|
private var suggestions: View? = null
|
|
39
39
|
private var wasActive = false
|
|
40
40
|
private var onActiveChanged: Runnable? = null
|
|
41
|
+
private var magnifier: BarButtonView? = null
|
|
41
42
|
|
|
42
43
|
/** The search of the screen on top opened or closed: the bar's hideOnScroll stops or goes on. */
|
|
43
44
|
fun setOnActiveChanged(listener: Runnable?) {
|
|
@@ -49,6 +50,7 @@ class StackSearchPresenter(
|
|
|
49
50
|
|
|
50
51
|
fun bindTopBar(topBar: TopBar) {
|
|
51
52
|
this.topBar = topBar
|
|
53
|
+
magnifier = null
|
|
52
54
|
// The suggestions hang from the bar: they follow its height as the search opens and its scopes show.
|
|
53
55
|
topBar.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ -> topBar.post { positionSuggestions(topBar) } }
|
|
54
56
|
}
|
|
@@ -91,28 +93,29 @@ class StackSearchPresenter(
|
|
|
91
93
|
return true
|
|
92
94
|
}
|
|
93
95
|
|
|
94
|
-
/**
|
|
96
|
+
/**
|
|
97
|
+
* After the right buttons change: the magnifier of an integrated search stands after them, before "⋮", as a button
|
|
98
|
+
* of the bar, with the id `<topBar.searchBar.testID>.button`.
|
|
99
|
+
*/
|
|
95
100
|
fun applyMagnifier() {
|
|
96
101
|
val bar = topBar ?: return
|
|
97
|
-
val
|
|
98
|
-
val
|
|
99
|
-
if (
|
|
100
|
-
|
|
102
|
+
val row = bar.rightButtonBar
|
|
103
|
+
val search = shown
|
|
104
|
+
if (search?.showsMagnifier != true) {
|
|
105
|
+
row.setTrailing(null)
|
|
101
106
|
return
|
|
102
107
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
setOnMenuItemClickListener {
|
|
112
|
-
shown?.activate()
|
|
113
|
-
true
|
|
114
|
-
}
|
|
108
|
+
val button = magnifier ?: BarButtonView(row.context).also { button ->
|
|
109
|
+
val context = styleContext()
|
|
110
|
+
val icon = AppCompatResources.getDrawable(context, AppCompatR.drawable.abc_ic_search_api_material)?.mutate()
|
|
111
|
+
icon?.setTint(TopBarDefaults.overflowIconColor(context))
|
|
112
|
+
val label = context.getString(AppCompatR.string.abc_searchview_description_search)
|
|
113
|
+
button.show(label, icon, null, true)
|
|
114
|
+
button.setOnClickListener { shown?.activate() }
|
|
115
|
+
magnifier = button
|
|
115
116
|
}
|
|
117
|
+
TestIds.apply(button, search.options.testID.get(null)?.let { "$it.button" })
|
|
118
|
+
row.setTrailing(button)
|
|
116
119
|
}
|
|
117
120
|
|
|
118
121
|
override fun refresh(search: ScreenSearch) {
|
|
@@ -132,7 +135,9 @@ class StackSearchPresenter(
|
|
|
132
135
|
fun onConfigurationChanged(tint: ThemeColour) {
|
|
133
136
|
shown?.takeTint(tint)
|
|
134
137
|
searches.values.forEach { it.restyle() }
|
|
135
|
-
|
|
138
|
+
// The magnifier is made again in the new mode's colors.
|
|
139
|
+
magnifier = null
|
|
140
|
+
topBar?.rightButtonBar?.setTrailing(null)
|
|
136
141
|
refresh()
|
|
137
142
|
}
|
|
138
143
|
|
|
@@ -231,10 +236,4 @@ class StackSearchPresenter(
|
|
|
231
236
|
lp.topMargin = top
|
|
232
237
|
card.layoutParams = lp
|
|
233
238
|
}
|
|
234
|
-
|
|
235
|
-
private companion object {
|
|
236
|
-
val MAGNIFIER_ID = View.generateViewId()
|
|
237
|
-
// The highest a menu order goes: after the screen's own buttons.
|
|
238
|
-
const val MAGNIFIER_ORDER = 0xFFFF
|
|
239
|
-
}
|
|
240
239
|
}
|