@apexnative/navigation 1.0.0-alpha.1 → 1.0.0-alpha.10
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 +120 -0
- package/README.md +147 -51
- package/android/CLAUDE.md +78 -25
- package/android/CORE.md +49 -25
- package/android/RECIPES.md +13 -6
- package/android/consumer-rules.pro +6 -0
- package/android/src/main/java/dev/apexnative/navigation/NavigationActivity.kt +85 -10
- package/android/src/main/java/dev/apexnative/navigation/NavigationApplication.kt +34 -13
- package/android/src/main/java/dev/apexnative/navigation/layout/LayoutChecks.kt +5 -1
- package/android/src/main/java/dev/apexnative/navigation/layout/LayoutNode.kt +6 -2
- package/android/src/main/java/dev/apexnative/navigation/nativescreen/NativeScreenContext.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/AnimationsOptions.kt +2 -2
- 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/ButtonMenuOptions.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/ButtonOptions.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/options/HardwareBackButtonOptions.kt +9 -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/OptionsCache.kt +8 -4
- package/android/src/main/java/dev/apexnative/navigation/options/SheetOptions.kt +7 -4
- package/android/src/main/java/dev/apexnative/navigation/options/SideMenuOptions.kt +6 -1
- package/android/src/main/java/dev/apexnative/navigation/options/StackAnimationOptions.kt +40 -2
- package/android/src/main/java/dev/apexnative/navigation/options/StatusBarOptions.kt +7 -3
- 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/options/UserChoices.kt +159 -0
- package/android/src/main/java/dev/apexnative/navigation/react/CommandAnswer.kt +29 -36
- package/android/src/main/java/dev/apexnative/navigation/react/CommandContract.kt +59 -0
- 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/ErrorTexts.kt +75 -60
- package/android/src/main/java/dev/apexnative/navigation/react/Hinge.kt +35 -23
- package/android/src/main/java/dev/apexnative/navigation/react/NavigationTurboModule.kt +12 -7
- package/android/src/main/java/dev/apexnative/navigation/react/OptionsCommands.kt +42 -4
- package/android/src/main/java/dev/apexnative/navigation/react/PendingCalls.kt +48 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ReactView.kt +54 -20
- package/android/src/main/java/dev/apexnative/navigation/react/ReloadCoordinator.kt +7 -6
- package/android/src/main/java/dev/apexnative/navigation/react/ScreenEnvironment.kt +177 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ScreenRegions.kt +19 -50
- package/android/src/main/java/dev/apexnative/navigation/react/ScrollEvents.kt +49 -128
- package/android/src/main/java/dev/apexnative/navigation/react/events/AppearanceDispatcher.kt +50 -81
- package/android/src/main/java/dev/apexnative/navigation/react/events/EventContract.kt +226 -0
- package/android/src/main/java/dev/apexnative/navigation/react/events/EventEmitter.kt +135 -94
- package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationState.kt +154 -0
- package/android/src/main/java/dev/apexnative/navigation/react/events/ScreenAppearance.kt +0 -6
- package/android/src/main/java/dev/apexnative/navigation/safearea/SafeAreaView.kt +12 -10
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotContainers.kt +10 -7
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotScreenView.kt +39 -19
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotView.kt +16 -4
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotViews.kt +40 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/ImageKey.kt +66 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/ImageLoader.kt +7 -89
- package/android/src/main/java/dev/apexnative/navigation/utils/ImageRequests.kt +76 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/MaterialTheme.kt +5 -6
- package/android/src/main/java/dev/apexnative/navigation/utils/OptionImages.kt +262 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/SystemAnimations.kt +36 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/UiUtils.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/utils/ViewController.kt +3 -1
- 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 +10 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/SecondaryScreenPresenter.kt +13 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/AppliedTabCalls.kt +49 -0
- 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 +108 -34
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsPresenter.kt +25 -24
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowGeometry.kt +22 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabItems.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabsRoom.kt +0 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentPresenter.kt +28 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentViewController.kt +12 -9
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ContentReadiness.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/RenderWait.kt +27 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenFrame.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenReadiness.kt +103 -56
- 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/ModalAnimations.kt +22 -24
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalCoordinator.kt +109 -21
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalRecord.kt +21 -6
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalSheet.kt +476 -73
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalViews.kt +57 -25
- 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 +83 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackCheck.kt +50 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackState.kt +49 -14
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/Navigator.kt +71 -12
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/RootCoordinator.kt +37 -11
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/overlay/OverlayCoordinator.kt +10 -8
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/Capabilities.kt +11 -4
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ContainerBackground.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ParentController.kt +6 -6
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuController.kt +42 -9
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuMotion.kt +19 -8
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuPresenter.kt +16 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuRules.kt +43 -4
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitPanes.kt +23 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitViewController.kt +77 -17
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/BackPreview.kt +315 -0
- 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 +30 -20
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackController.kt +216 -18
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackDisplay.kt +26 -1
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackQueue.kt +149 -41
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackTransitions.kt +26 -8
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackViews.kt +115 -6
- 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 +222 -48
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/ScreenSearch.kt +3 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/StackSearchPresenter.kt +30 -34
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarComponents.kt +5 -51
- 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/MenuChecks.kt +13 -56
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarPresenter.kt +219 -54
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarVisibility.kt +9 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ScrollEventListener.kt +6 -9
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ViewController.kt +75 -21
- package/android/src/main/java/dev/apexnative/navigation/views/animations/AnimationLayer.kt +73 -0
- package/android/src/main/java/dev/apexnative/navigation/views/animations/Curves.kt +29 -11
- package/android/src/main/java/dev/apexnative/navigation/views/animations/ValueInterpolation.kt +14 -0
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabs.kt +9 -7
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabsLayout.kt +61 -2
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomBottomTabItemView.kt +0 -5
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomTabRow.kt +72 -10
- package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStep.kt +31 -0
- package/android/src/main/java/dev/apexnative/navigation/views/element/ElementTransitions.kt +143 -135
- package/android/src/main/java/dev/apexnative/navigation/views/element/TargetsWait.kt +13 -5
- package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionLayer.kt +37 -112
- package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionTargets.kt +9 -6
- package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionViews.kt +100 -0
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ElementPictures.kt +112 -4
- 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 +56 -41
- 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/sidemenu/SideMenuView.kt +12 -3
- package/android/src/main/java/dev/apexnative/navigation/views/stack/ScreenEdge.kt +45 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/StackLayout.kt +140 -1
- package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/Fab.kt +14 -10
- 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 -17
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TopBar.kt +73 -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 +125 -178
- 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/app.js +1 -1
- package/cli/doctor/checks/app.js +77 -14
- package/cli/doctor/checks/splash.js +4 -22
- package/cli/migrate/native.js +18 -0
- package/cli/project.js +10 -2
- package/cli/setup/index.js +18 -0
- package/cli/setup/source.js +2 -1
- package/cli/setup/steps/appDelegate.js +66 -11
- package/cli/setup/steps/mainApplication.js +134 -19
- package/cli/setup/steps/metro.js +46 -0
- package/cli/setup/steps/sceneDelegate.js +108 -0
- package/cli/splash/index.js +3 -1
- 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 +58 -12
- package/docs-md/containers/modals.md +8 -4
- package/docs-md/containers/overlays.md +3 -1
- package/docs-md/containers/side-menu.md +19 -2
- package/docs-md/containers/tabs.md +5 -1
- package/docs-md/flows/bottom-sheets.md +4 -2
- package/docs-md/flows/forms-in-a-modal.md +1 -1
- 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 +4 -3
- package/docs-md/guides/deep-links.md +15 -33
- package/docs-md/help/glossary.md +4 -4
- package/docs-md/help/troubleshooting.md +44 -6
- package/docs-md/index.json +57 -1
- package/docs-md/migration/from-expo-router.md +1 -1
- package/docs-md/migration/from-react-native-navigation.md +9 -3
- package/docs-md/migration/from-react-navigation.md +2 -2
- package/docs-md/screen-ui/back-and-gestures.md +46 -2
- 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 +17 -12
- 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 +21 -3
- 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 +61 -13
- package/ios/Animations/ANNTransitionPlan.h +2 -2
- package/ios/Animations/ANNTransitionPlan.mm +10 -0
- package/ios/Animations/ANNTransitionWait.mm +6 -7
- package/ios/Animations/Elements/ANNElementFinder.h +57 -0
- package/ios/Animations/Elements/ANNElementFinder.mm +174 -2
- package/ios/Animations/Elements/ANNElementTransition.h +10 -8
- package/ios/Animations/Elements/ANNElementTransition.mm +19 -21
- package/ios/Animations/Elements/ANNSharedElementFlight.h +16 -11
- package/ios/Animations/Elements/ANNSharedElementFlight.mm +308 -69
- 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 +60 -24
- package/ios/CORE.md +44 -34
- package/ios/Contract/ANNCommandAnswer.h +13 -5
- package/ios/Contract/ANNCommandAnswer.mm +40 -32
- package/ios/Contract/ANNCommandContract.h +15 -0
- package/ios/Contract/ANNCommandContract.mm +78 -0
- package/ios/Contract/ANNCommandRunner.h +10 -9
- package/ios/Contract/ANNCommandRunner.mm +22 -28
- package/ios/Contract/ANNErrorTexts.h +6 -2
- package/ios/Contract/ANNErrorTexts.mm +18 -10
- package/ios/Contract/ANNLayoutNode.h +3 -3
- package/ios/Contract/ANNLayoutReader.h +3 -3
- package/ios/Core/ANNAppDelegate.mm +0 -2
- package/ios/Core/ANNAppearanceDispatcher.h +5 -4
- package/ios/Core/ANNAppearanceDispatcher.mm +12 -1
- package/ios/Core/ANNDeepLinkQueue.h +22 -2
- package/ios/Core/ANNDeepLinkQueue.mm +121 -14
- package/ios/Core/ANNErrorHandler.h +9 -4
- package/ios/Core/ANNErrorHandler.mm +20 -2
- package/ios/Core/ANNEventContract.h +246 -0
- package/ios/Core/ANNEventContract.mm +225 -0
- package/ios/Core/ANNEventEmitter.h +6 -2
- package/ios/Core/ANNEventEmitter.mm +117 -80
- package/ios/Core/ANNHinge.h +6 -0
- package/ios/Core/ANNHinge.mm +15 -4
- package/ios/Core/ANNJavaScriptCalls.h +33 -0
- package/ios/Core/ANNJavaScriptCalls.mm +52 -0
- package/ios/Core/ANNLayoutProtocol.h +5 -5
- package/ios/Core/ANNNavigationState.h +7 -5
- package/ios/Core/ANNNavigationState.mm +8 -7
- package/ios/Core/ANNNodeHelper.h +32 -12
- package/ios/Core/ANNNodeHelper.mm +100 -3
- package/ios/Core/ANNParking.h +5 -4
- package/ios/Core/ANNReloadCoordinator.mm +5 -12
- package/ios/Core/ANNRenderWait.h +20 -6
- package/ios/Core/ANNRenderWait.mm +143 -56
- package/ios/Core/ANNSceneDelegate.mm +25 -15
- package/ios/Core/ANNSystemUI.h +3 -2
- package/ios/Core/ANNSystemUI.mm +7 -0
- package/ios/Core/ANNUtils.h +7 -0
- package/ios/Core/ANNUtils.mm +10 -0
- package/ios/Core/ApexNavigation+Internal.h +1 -1
- package/ios/Core/ApexNavigation.mm +7 -6
- package/ios/Core/UIViewController+LayoutProtocol.h +9 -2
- package/ios/Core/UIViewController+LayoutProtocol.mm +8 -0
- package/ios/Layouts/Arrangement/ANNArrangementState.h +2 -17
- package/ios/Layouts/Arrangement/ANNArrangementState.mm +0 -38
- package/ios/Layouts/Arrangement/ANNArrangementViewController.mm +10 -8
- package/ios/Layouts/Modal/ANNModalCoordinator.h +1 -1
- package/ios/Layouts/Modal/ANNModalCoordinator.mm +57 -16
- package/ios/Layouts/Modal/ANNModalPresentation.h +8 -5
- package/ios/Layouts/Modal/ANNModalPresentation.mm +12 -12
- package/ios/Layouts/Modal/ANNSheetPresenter.mm +83 -1
- package/ios/Layouts/Overlay/ANNOverlayCoordinator.mm +2 -8
- package/ios/Layouts/Root/ANNRootCoordinator.mm +58 -19
- package/ios/Layouts/Root/ANNSplashViewController.h +5 -3
- package/ios/Layouts/Root/ANNSplashViewController.mm +147 -0
- package/ios/Layouts/Screen/ANNComponentPresenter.h +11 -3
- package/ios/Layouts/Screen/ANNComponentPresenter.mm +34 -6
- package/ios/Layouts/Screen/ANNComponentViewController.h +15 -13
- package/ios/Layouts/Screen/ANNComponentViewController.mm +130 -75
- package/ios/Layouts/Screen/ANNNativeScreenContext.mm +7 -5
- 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/ANNScreenPlace.h +53 -0
- package/ios/Layouts/Screen/ANNScreenPlace.mm +205 -0
- package/ios/Layouts/Screen/ANNScreenRegions.h +3 -18
- package/ios/Layouts/Screen/ANNScreenRegions.mm +9 -44
- package/ios/Layouts/Screen/ANNScreenSafeArea.h +4 -9
- package/ios/Layouts/Screen/ANNScreenSafeArea.mm +14 -16
- package/ios/Layouts/Screen/ANNScreenSettling.h +32 -0
- package/ios/Layouts/Screen/ANNScreenSettling.mm +137 -0
- package/ios/Layouts/SideMenu/ANNSideMenuTypes.h +8 -0
- package/ios/Layouts/SideMenu/ANNSideMenuViewController.mm +83 -14
- package/ios/Layouts/SplitView/ANNSplitViewCommands.h +3 -2
- package/ios/Layouts/SplitView/ANNSplitViewCommands.mm +105 -39
- package/ios/Layouts/SplitView/ANNSplitViewController.mm +7 -8
- package/ios/Layouts/Stack/ANNPreviewPush.h +7 -6
- package/ios/Layouts/Stack/ANNPreviewPush.mm +142 -27
- package/ios/Layouts/Stack/ANNStackAnimatingDelegate.h +11 -2
- package/ios/Layouts/Stack/ANNStackAnimatingDelegate.mm +14 -7
- package/ios/Layouts/Stack/ANNStackCommands.mm +1 -0
- package/ios/Layouts/Stack/ANNStackController.h +8 -0
- package/ios/Layouts/Stack/ANNStackController.mm +184 -16
- package/ios/Layouts/Stack/ANNStackQueue.h +5 -2
- package/ios/Layouts/Stack/ANNStackQueue.mm +56 -43
- 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/Stack/UINavigationController+ANNCommands.h +4 -2
- package/ios/Layouts/Stack/UINavigationController+ANNCommands.mm +2 -3
- package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.h +4 -0
- package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.mm +11 -0
- package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.h +12 -1
- package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.mm +23 -0
- package/ios/Layouts/Tabs/ANNBottomTabsController.h +3 -0
- package/ios/Layouts/Tabs/ANNBottomTabsController.mm +237 -57
- package/ios/Layouts/Tabs/ANNBottomTabsCustomRow.mm +8 -3
- package/ios/Layouts/Tabs/ANNBottomTabsPresenter.h +6 -2
- package/ios/Layouts/Tabs/ANNBottomTabsPresenter.mm +232 -43
- 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/ANNOptionsCache.h +7 -6
- package/ios/Options/ANNOptionsReader.mm +108 -0
- package/ios/Options/ANNSearchBarOptions.h +4 -3
- package/ios/Options/ANNSheetOptions.h +4 -1
- package/ios/Options/ANNSideMenuOptions.h +2 -0
- package/ios/Options/ANNSideMenuOptions.mm +2 -0
- package/ios/Options/ANNStackPopAnimationOptions.h +13 -0
- package/ios/Options/ANNStackPopAnimationOptions.mm +11 -0
- package/ios/Options/ANNUserChoice.h +57 -0
- package/ios/Options/ANNUserChoice.mm +44 -0
- package/ios/Options/Params/ANNImageSource.h +61 -0
- package/ios/Options/Params/ANNImageSource.mm +101 -0
- package/ios/Options/Params/ANNOptionImages.h +37 -0
- package/ios/Options/Params/ANNOptionImages.mm +284 -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 +15 -2
- package/ios/Options/Params/Image.mm +35 -2
- package/ios/Options/Params/ImageParser.h +5 -5
- package/ios/Options/Params/ImageParser.mm +28 -46
- package/ios/Public/ApexNavigation/ANNSceneDelegate.h +3 -0
- package/ios/Public/ApexNavigation/ApexNavigation.h +1 -1
- package/ios/RECIPES.md +13 -6
- package/ios/React/ANNReactView.mm +6 -25
- package/ios/React/ANNSafeAreaViewComponentView.mm +28 -17
- package/ios/React/ANNSurfaceHostingView.h +14 -0
- package/ios/React/ANNSurfaceHostingView.mm +144 -1
- package/ios/React/Slots/ANNSlotComponentView.mm +24 -17
- package/ios/React/Slots/ANNSlotContainers.h +14 -6
- package/ios/React/Slots/ANNSlotContainers.mm +75 -2
- package/ios/React/Slots/ANNSlotHost.mm +1 -3
- 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 +14 -8
- package/ios/TopBar/ANNBarButtons.mm +397 -80
- package/ios/TopBar/ANNIconButtonImage.h +1 -0
- package/ios/TopBar/ANNIconButtonImage.mm +34 -1
- package/ios/TopBar/ANNLargeTitlePresenter.h +13 -0
- package/ios/TopBar/ANNLargeTitlePresenter.mm +50 -7
- 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 +172 -21
- package/ios/TopBar/ANNSearchResultsViewController.mm +29 -6
- package/ios/TopBar/ANNTopBarPresenter.h +8 -2
- package/ios/TopBar/ANNTopBarPresenter.mm +155 -33
- package/ios/TurboModules/ANNTurboEventEmitter.mm +4 -35
- package/ios/TurboModules/ANNTurboModule.mm +104 -33
- 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 +40 -27
- 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 +190 -66
- package/lib/module/api/app/createNavigation.js.map +1 -1
- package/lib/module/api/commands/commands.js +54 -6
- package/lib/module/api/commands/commands.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/useNavigation.js +8 -3
- package/lib/module/api/hooks/useNavigation.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/dispatchedLinks.js +23 -0
- package/lib/module/api/linking/dispatchedLinks.js.map +1 -0
- package/lib/module/api/linking/linking.js +11 -0
- package/lib/module/api/linking/linking.js.map +1 -1
- package/lib/module/api/navigation.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 +193 -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 +51 -9
- package/lib/module/engine/commands.js.map +1 -1
- package/lib/module/engine/layout.js +20 -11
- 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 +49 -15
- 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/places.js +52 -7
- package/lib/module/engine/places.js.map +1 -1
- package/lib/module/engine/props.js +30 -1
- package/lib/module/engine/props.js.map +1 -1
- package/lib/module/engine/refresh.js +85 -0
- package/lib/module/engine/refresh.js.map +1 -0
- package/lib/module/engine/rememberedOptions.js +61 -1
- package/lib/module/engine/rememberedOptions.js.map +1 -1
- package/lib/module/engine/screens.js +77 -16
- package/lib/module/engine/screens.js.map +1 -1
- package/lib/module/interfaces/contract/commands.json +101 -0
- package/lib/module/interfaces/contract/errors.json +275 -0
- package/lib/typescript/adapters/NativeANNTurboModule.d.ts +12 -2
- 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/commands/commands.d.ts.map +1 -1
- package/lib/typescript/api/commands/presentation.d.ts +4 -3
- package/lib/typescript/api/commands/presentation.d.ts.map +1 -1
- package/lib/typescript/api/events/navigationEvents.d.ts +3 -3
- package/lib/typescript/api/events/navigationEvents.d.ts.map +1 -1
- package/lib/typescript/api/hooks/useNavigation.d.ts +1 -1
- package/lib/typescript/api/hooks/useNavigation.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/dispatchedLinks.d.ts +7 -0
- package/lib/typescript/api/linking/dispatchedLinks.d.ts.map +1 -0
- 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/navigation.d.ts +4 -1
- package/lib/typescript/api/navigation.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/options.d.ts +5 -2
- package/lib/typescript/engine/options.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/places.d.ts +7 -2
- package/lib/typescript/engine/places.d.ts.map +1 -1
- package/lib/typescript/engine/props.d.ts +8 -1
- package/lib/typescript/engine/props.d.ts.map +1 -1
- 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 +4 -4
- package/lib/typescript/interfaces/ComponentEvents.d.ts.map +1 -1
- package/lib/typescript/interfaces/Events.d.ts +28 -10
- package/lib/typescript/interfaces/Events.d.ts.map +1 -1
- package/lib/typescript/interfaces/Options.d.ts +1 -1
- package/lib/typescript/interfaces/Options.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/animations.d.ts +80 -22
- package/lib/typescript/interfaces/options/animations.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/bottomTabs.d.ts +21 -7
- package/lib/typescript/interfaces/options/bottomTabs.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/buttons.d.ts +23 -15
- package/lib/typescript/interfaces/options/buttons.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/modals.d.ts +34 -26
- package/lib/typescript/interfaces/options/modals.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/sideMenu.d.ts +23 -6
- package/lib/typescript/interfaces/options/sideMenu.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/stack.d.ts +17 -3
- package/lib/typescript/interfaces/options/stack.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/system.d.ts +18 -11
- 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 +68 -38
- 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 +40 -27
- package/src/adapters/NativeANNTurboModule.ts +12 -2
- package/src/api/app/AppRegistry.ts +16 -2
- package/src/api/app/createNavigation.ts +203 -69
- package/src/api/commands/commands.ts +48 -7
- package/src/api/commands/presentation.ts +4 -3
- package/src/api/events/navigationEvents.ts +10 -4
- package/src/api/hooks/useNavigation.ts +9 -4
- package/src/api/hooks/useSafeAreaInsets.ts +4 -3
- package/src/api/index.ts +1 -0
- package/src/api/linking/dispatchedLinks.ts +18 -0
- package/src/api/linking/linking.ts +22 -1
- package/src/api/navigation.ts +4 -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 +185 -42
- package/src/api/theme/theme.ts +5 -0
- package/src/engine/commands.ts +70 -13
- package/src/engine/layout.ts +27 -11
- package/src/engine/nativeScreens.ts +10 -1
- package/src/engine/options.ts +45 -19
- package/src/engine/optionsChange.ts +107 -0
- package/src/engine/places.ts +65 -7
- package/src/engine/props.ts +30 -1
- package/src/engine/refresh.ts +97 -0
- package/src/engine/rememberedOptions.ts +74 -1
- package/src/engine/screens.tsx +76 -21
- package/src/interfaces/ComponentEvents.ts +4 -4
- package/src/interfaces/Events.ts +29 -10
- package/src/interfaces/Options.ts +1 -0
- package/src/interfaces/contract/commands.json +101 -0
- package/src/interfaces/contract/errors.json +275 -0
- package/src/interfaces/options/animations.ts +81 -22
- package/src/interfaces/options/bottomTabs.ts +21 -7
- package/src/interfaces/options/buttons.ts +23 -15
- package/src/interfaces/options/modals.ts +34 -26
- package/src/interfaces/options/sideMenu.ts +24 -6
- package/src/interfaces/options/stack.ts +17 -3
- package/src/interfaces/options/system.ts +18 -11
- package/src/interfaces/options/toolbar.ts +2 -2
- package/src/interfaces/options/topBar.ts +68 -38
- package/android/src/main/java/dev/apexnative/navigation/react/ArrangementStates.kt +0 -41
- package/android/src/main/java/dev/apexnative/navigation/react/ScreenInsets.kt +0 -69
- package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationStateReporter.kt +0 -62
- package/android/src/main/java/dev/apexnative/navigation/react/events/StateHold.kt +0 -62
- 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 -138
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PlainViewAnimator.kt +0 -88
- 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 -66
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextChangeAnimator.kt +0 -179
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewChangeAnimator.kt +0 -139
- package/ios/Layouts/Screen/ANNScreenInsets.h +0 -30
- package/ios/Layouts/Screen/ANNScreenInsets.mm +0 -68
- package/ios/Layouts/Tabs/ANNTabsPreloadWindow.h +0 -27
- package/ios/Layouts/Tabs/ANNTabsPreloadWindow.mm +0 -55
package/android/CORE.md
CHANGED
|
@@ -10,7 +10,7 @@ otherwise.
|
|
|
10
10
|
```
|
|
11
11
|
JS ─ ANNTurboModule (codegen NativeANNTurboModuleSpec)
|
|
12
12
|
│ sync getters answer on the JS thread from stores the main thread fills
|
|
13
|
-
│ (
|
|
13
|
+
│ (ScreenEnvironment, Hinge, StartInfo)
|
|
14
14
|
▼ module thread
|
|
15
15
|
react/NavigationTurboModule one override per method
|
|
16
16
|
│ layout/LayoutReader ► options/OptionsReader the whole layout read and checked, its options read
|
|
@@ -31,7 +31,7 @@ coordinators: RootCoordinator · StackQueue (one per stack) · ModalCoordinator
|
|
|
31
31
|
presenters: ComponentPresenter · StackPresenter + TopBarPresenter · BottomTabsPresenter · SideMenuPresenter ·
|
|
32
32
|
SplitViewPresenter · system/SystemUiOwner (status bar, navigation bar, orientation, keyboard)
|
|
33
33
|
▼
|
|
34
|
-
react/events/AppearanceDispatcher ─►
|
|
34
|
+
react/events/AppearanceDispatcher ─► NavigationState ─► EventEmitter ─► ANN.* events ─► JS
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
- **Way in.** `NavigationTurboModule` only turns a method into a `CommandRunner` call; it holds no navigation logic. It
|
|
@@ -72,18 +72,24 @@ react/events/AppearanceDispatcher ─► NavigationStateReporter ─► EventEmi
|
|
|
72
72
|
5. **Make and join.** `LayoutFactory.create` makes Profile (a `ComponentViewController`, registered in the
|
|
73
73
|
`ChildControllersRegistry`); `StackController.join` adds it; `StackQueue.push` accepts it as an entry.
|
|
74
74
|
6. **`StackQueue`** is the only way to change a stack's children. `drain` starts the operation when nothing blocks it.
|
|
75
|
-
`startPush` decides the wait:
|
|
76
|
-
|
|
75
|
+
`startPush` decides the wait: a prepared push; `waitForRender: true` (as long as it takes); unset, for a screen with
|
|
76
|
+
React content, Profile's first mount, 0.5 s at most (`PUSH_WAIT_MILLIS`); none for `false`, a native screen or a
|
|
77
|
+
stack off screen. A wait is a `RenderWait` on Profile. Its mount reaches the push through the queue's `afterCalls`
|
|
78
|
+
(`PendingCalls`: once through the JavaScript thread, the module's thread and the main thread, the way of a
|
|
79
|
+
`mergeOptions`), so the `mergeOptions` of the commit that mounted it (`useScreenOptions`) has applied when the
|
|
80
|
+
transition starts, content mounted before the push too; the prepared push starts the same way after its slot
|
|
81
|
+
mounted. Unset, the targets of elements take what is left of the 0.5 s.
|
|
77
82
|
7. **Begin.** `beginPush` raises Profile's view (`StackViews`), moves the bar and the tab bar
|
|
78
83
|
(`StackQueue.Host.barTransition`, `tabBarTransition`), calls `StackController` through `currentChildChanged`, then
|
|
79
84
|
`AppearanceDispatcher.beginTransition`: **`ComponentWillAppear`** of Profile. The transition runs
|
|
80
85
|
(`StackTransitions`, `SystemTransition`, or the screens' own animation, `AnimationRules.stackIsOwn`).
|
|
81
86
|
8. **End.** `finishPush` calls `AppearanceDispatcher.endTransition`: **`ComponentDidDisappear`** of Home, then
|
|
82
|
-
**`ComponentDidAppear`** of Profile, then
|
|
83
|
-
transition's own events (none for a push), then
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
**`ComponentDidAppear`** of Profile, then the answer's one state step (`CommandAnswer.reportStateNow`:
|
|
88
|
+
**`NavigationStateChanged`**, only if it changed), then the transition's own events (none for a push), then
|
|
89
|
+
`CommandAnswer.resolve` with Profile's id.
|
|
90
|
+
9. **Answer.** `resolve` sends the state only when no transition sent it (`reportStateNow` runs once per answer: a
|
|
91
|
+
`setRoot` with layout modals sends it here), resolves the promise, then sends **`CommandCompleted`**
|
|
92
|
+
(`CommandContract.COMPLETED`). After the task, `BackCallbackState.update` recomputes what back does.
|
|
87
93
|
|
|
88
94
|
The events go from the main thread, synchronously, through `EventEmitter.current()`; the promise is answered once.
|
|
89
95
|
|
|
@@ -91,7 +97,9 @@ The events go from the main thread, synchronously, through `EventEmitter.current
|
|
|
91
97
|
current root in the root layer, transparent (`RootLayerViews.place`), so its React roots start while the old root keeps
|
|
92
98
|
the touches. It waits (`RenderWait`, by `animations.setRoot.enter.waitForRender`), then fades through or plays its own
|
|
93
99
|
animation, the old root is destroyed with its `ComponentDidDisappear`, `NativeScreenReleased` and `SlotDestroyed`, and
|
|
94
|
-
the end steps and answer are the same. The layout's modals and overlays show after it, one by one, before the answer
|
|
100
|
+
the end steps and answer are the same. The layout's modals and overlays show after it, one by one, before the answer;
|
|
101
|
+
its modals are made with the root and render unseen in the modals layer, held (`ModalCoordinator.hold`), so each
|
|
102
|
+
shows in its turn without a wait of its own.
|
|
95
103
|
The last `setRoot` wins: an older one is rejected (`ErrorTexts.setRootReplaced`) or finished at once.
|
|
96
104
|
- **`showModal`** (`Navigator.showModal`, `ModalCoordinator.show`). One `ModalRecord` per modal; it joins the modals
|
|
97
105
|
layer unseen (`ModalViews`), waits with its own `RenderWait`, then slides in (or opens as a `ModalSheet`). It shows
|
|
@@ -120,13 +128,16 @@ Each rule has one owner. Change the owner, not a caller; if a new feature needs
|
|
|
120
128
|
`beginTransition` starts the appearances; `endTransition` runs what left, then what came, then the state, then the
|
|
121
129
|
transition's events, then the answer. Events asked before a screen's content is ready are held in its
|
|
122
130
|
`ScreenAppearance` (until the content mounts or `HOLD_LIMIT_MILLIS`).
|
|
123
|
-
- **Navigation state.** `
|
|
124
|
-
|
|
125
|
-
`
|
|
126
|
-
|
|
131
|
+
- **Navigation state.** `NavigationState` owns it: the last state sent, the walk (`stateOf`), the posted update and its
|
|
132
|
+
holds (`NavigationState.Updates`). `AppearanceDispatcher.state` (`StateUpdates`) is the one way to ask for it:
|
|
133
|
+
`setNeedsUpdate` coalesces the asks to one posted update per pass of the main loop and keeps it while held; the
|
|
134
|
+
update calls `updateNow`. A command's answer sends it once, at once and never held (`CommandAnswer.reportStateNow`):
|
|
135
|
+
at the end of its transition, else right before its promise for the commands that change what shows; nothing for a
|
|
136
|
+
JavaScript that went. It reads the navigator through `Navigators.current()`, and `stateOf` finds the
|
|
127
137
|
`tab` as the nearest tabs of the visible screen (the last tabs met walking down from the visible layout). A `setRoot`
|
|
128
138
|
with layout modals or overlays takes `AppearanceDispatcher.StateUpdates.hold()` and releases it right before its
|
|
129
|
-
answer, so JavaScript hears one state; every hold has one `release()`.
|
|
139
|
+
answer, so JavaScript hears one state; every hold has one `release()`. The holds go when the JavaScript goes
|
|
140
|
+
(`NavigationState.javaScriptWent`), so one left by its `setRoot` never holds the next JavaScript's updates.
|
|
130
141
|
- **Answer.** `CommandAnswer`: resolves or rejects once, and nothing once the JavaScript went. The id a stack entry
|
|
131
142
|
answers with is one rule, `StackController.answerIdOf` (the queue asks it through `StackQueue.Host.answerIdOf` with
|
|
132
143
|
an `AnswerKind`): `push` answers the entry's own id (a pair's), every other command the screen it stands for (a
|
|
@@ -134,7 +145,11 @@ Each rule has one owner. Change the owner, not a caller; if a new feature needs
|
|
|
134
145
|
- **Stack queue.** `StackQueue`: every command, back and return of a container goes through it; it keeps `entries`
|
|
135
146
|
(what JavaScript sees) and `shown` (what the container shows) and answers once.
|
|
136
147
|
- **Screen readiness.** `ScreenReadiness` (by id; written by `SafeAreaView`) and `ContentReadiness` (the `Readiness`
|
|
137
|
-
the waits ask, through `IReactView.isReady`).
|
|
148
|
+
the waits ask, through `IReactView.isReady`). As on iOS, the signals are kept (a listener that comes later hears them
|
|
149
|
+
at once), an id has a listener per key (several roots of one bar component), and each signal carries the React
|
|
150
|
+
surface it came from: a `ReactView` takes only its own surface's, so an old root with the same id never makes a new
|
|
151
|
+
one ready. An id renders at once while a root marks it (`ReactView`'s `rendersAtOnce`); the last one takes the id's
|
|
152
|
+
signals with it. A screen's id is cleared as the screen is made and destroyed, everything on reload.
|
|
138
153
|
- **Render wait.** `RenderWait`: the one wait for screens to render, used by `RootCoordinator`, `ModalCoordinator`,
|
|
139
154
|
`OverlayCoordinator` and `StackQueue`; `RenderWait.waitedScreens` walks `ParentController.waitedChildren()` at every
|
|
140
155
|
level. What differs between users are values (limit, bar phase, unknown-content rule), never steps.
|
|
@@ -164,12 +179,16 @@ Each rule has one owner. Change the owner, not a caller; if a new feature needs
|
|
|
164
179
|
- **Back.** `NavigationActivity.passBack` → `ReactGateway.onBackPressed` (JavaScript's `BackHandler`) →
|
|
165
180
|
`invokeDefaultOnBackPressed` → `Navigator.handleBack` → `ModalCoordinator.handleBack` → the root's
|
|
166
181
|
`ParentController.handleBack` → `StackController.handleBack` → `StackQueue.cut`. `BackCallbackState` keeps the
|
|
167
|
-
system callback enabled only while back has something to do
|
|
168
|
-
|
|
182
|
+
system callback enabled only while back has something to do, computed again on the events that change it (its KDoc
|
|
183
|
+
lists them), never before each frame; debug builds check it (`BackCallbackCheck`).
|
|
184
|
+
- **Error texts.** `ErrorTexts`: one function per text, the same words as iOS, made with iOS's from
|
|
185
|
+
`src/interfaces/contract/errors.json` (`scripts/contract.mjs`). JavaScript adds `[navigation] <command>:`.
|
|
186
|
+
- **Event names and keys.** `EventContract`, made from the event types of `src/interfaces/`; `EventEmitter` and the
|
|
187
|
+
builders of payloads use it, never a string.
|
|
169
188
|
- **Room for the bars.** A screen's room at the top and bottom is `ScreenFrame` with `ScreenSafeArea` and the
|
|
170
189
|
`ParentController` room hooks (`getTopInset`, `keepsStatusBarRoomOf`, …). A screen in a pair forwards its room to
|
|
171
190
|
the pair (`ScreenFrame.applyRoom`), and the pair's `getTopInset` uses the screens' rule (`ScreenFrame.topRoomOf`)
|
|
172
|
-
with the options it shows with. A view's place in the window for the safe area (the React root, the stack's header
|
|
191
|
+
with the options it shows with. The bottom edge is not padded by default (only `'bottom'` in the edges pads it); `roomPadding` still shrinks the view for an opaque navigation bar and the keyboard. A view's place in the window for the safe area (the React root, the stack's header
|
|
173
192
|
bottom in `headerBottomOf`, the tabs' top in `tabsTopOf`) is `RestPlace`: from layout, without translations, a sheet
|
|
174
193
|
at rest.
|
|
175
194
|
- **A container's own move.** A container that moves children in or out of the window without a command (the split
|
|
@@ -188,11 +207,12 @@ Modules are the feature classes that plug into the core through its contract (th
|
|
|
188
207
|
custom row (`BottomTabsCustomRowOptions`).
|
|
189
208
|
- **Views and helpers:** tabs bar (`BottomTabs`, `BottomTabItem`, `BottomTabsCollapseBehavior`, `scrollToTop`), slots
|
|
190
209
|
(`SlotHost`, `SlotView`, `SlotContainers`), safe area (`SafeAreaView`), native screens (`nativescreen/`), splash
|
|
191
|
-
(`splash/`), animations (`FadeThrough`, `SystemTransition`, `TransitionTargets`,
|
|
192
|
-
(`MaterialTheme`, `NavigationLog`, `awaitBarComponents`,
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
210
|
+
(`splash/`), animations (`FadeThrough`, `SystemTransition`, `TransitionTargets`, the copies of shared elements:
|
|
211
|
+
`TextMorph`, `ViewMorph`, `ImageMorph`), utils (`MaterialTheme`, `NavigationLog`, `awaitBarComponents`,
|
|
212
|
+
`whenDrawn`).
|
|
213
|
+
- **Stores and singletons:** a screen's environment (`ScreenEnvironment`: its insets and padding, its regions as
|
|
214
|
+
`ScreenRegions` measures them, its pair state), the window (`Hinge`, `WindowFolds`), links (`LaunchLink`,
|
|
215
|
+
`StartInfo`), events (`NavigationState`), commands (`BackCallbackState`), stack (`PreparedFrame`).
|
|
196
216
|
|
|
197
217
|
How they plug in:
|
|
198
218
|
|
|
@@ -216,4 +236,8 @@ How they plug in:
|
|
|
216
236
|
- **Core code in a module's folder:** `viewcontrollers/splitview/SplitViewPresenter.kt`, `slots/SlotScreenView.kt`,
|
|
217
237
|
and in `views/animations/` and `views/element/` everything except the files named above.
|
|
218
238
|
- **Stores** are written on the main thread by the core and read from any thread; they are cleared with their nodes and on
|
|
219
|
-
reload.
|
|
239
|
+
reload. A screen's environment is one immutable record per id in `ScreenEnvironment` (insets for JavaScript, padding,
|
|
240
|
+
regions, pair state), replaced at once; the screen's node clears it with one `remove` when it is destroyed, unless a
|
|
241
|
+
later node has its id; the padding listeners of its safe area views stay until the views stop. Their events, and
|
|
242
|
+
the search's, go through the emitter of the JavaScript the screen was made for
|
|
243
|
+
(`EventEmitter.of(node.jsGeneration)`); the hinge keeps the `EventEmitter.current()` of the call that turned it on.
|
package/android/RECIPES.md
CHANGED
|
@@ -14,7 +14,11 @@ The steps for adding an option and for adding a command to the Android core; rea
|
|
|
14
14
|
(a repaint after a light/dark switch or `setDefaultOptions`); a system-bar option goes through `SystemUiRules`.
|
|
15
15
|
Read colors with `ThemeColour.get` at apply so they follow the theme.
|
|
16
16
|
4. The cache needs nothing: own options are written only through `ViewController.options`, `changeOptions` and
|
|
17
|
-
`mergeOptions
|
|
17
|
+
`mergeOptions` (`mergeOwnOptions`), defaults only through `DefaultOptions.set`. Never change a resolved result.
|
|
18
|
+
What the user chooses in the native UI (a menu's check, a search scope) is not written into own options: it goes
|
|
19
|
+
into the node's user layer through `ViewController.changeChoices` (`options/UserChoices.kt`), which applies it by
|
|
20
|
+
id over the resolved options and lets it go when a merge changes that field. A new kind of choice is a field of
|
|
21
|
+
`UserChoices` with its `applyTo` and `yieldTo`; `changeOptions` stays for the library's own bookkeeping of a merge.
|
|
18
22
|
5. Tests: add the field to `OptionsFixture.full()`. `WholeTreeTest` walks the tree by reflection and fails when a field
|
|
19
23
|
is not read, copied, merged or defaulted. Add cases to `ReadersTest`, `MergeRuleTest` and the area's rules test.
|
|
20
24
|
6. The docs page and a Showcase control; one meaning on both platforms, and where Android can't do it the JSDoc says so
|
|
@@ -29,11 +33,14 @@ The steps for adding an option and for adding a command to the Android core; rea
|
|
|
29
33
|
3. The body goes to the owner of the area: `Navigator` (root, modals, overlays), `StackCommands` (stacks), a
|
|
30
34
|
coordinator. A stack operation is a `StackQueue` operation.
|
|
31
35
|
4. New layout fields are read and checked in `LayoutReader`; checks against what shows are in `LayoutChecks` or in the
|
|
32
|
-
command, before any node is made. Every rejection text is a function in `ErrorTexts` (same words as iOS)
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
command, before any node is made. Every rejection text is a function in `ErrorTexts` (same words as iOS),
|
|
37
|
+
made by `node scripts/contract.mjs` from `src/interfaces/contract/errors.json`: a new text goes there.
|
|
38
|
+
5. The answer goes through `CommandAnswer`: give the command its entry in `src/interfaces/contract/commands.json`
|
|
39
|
+
(what it resolves with, `state` when it may change what shows, `completed` when it shows or dismisses) and run
|
|
40
|
+
`node scripts/contract.mjs`, which makes `CommandContract` (then the state, the promise and `CommandCompleted` follow
|
|
41
|
+
in that order). A transition ends through
|
|
35
42
|
`AppearanceDispatcher.endTransition`.
|
|
36
43
|
6. Tests: `CommandRunnerTest`, `CommandAnswerTest`, `ErrorTextsTest`, `LayoutReaderTest`; a stack operation also needs a
|
|
37
44
|
case in the queue tests (`StackQueueHarness`).
|
|
38
|
-
7. A new event:
|
|
39
|
-
`AppearanceDispatcher.Sender`.
|
|
45
|
+
7. A new event: the payload type in `src/interfaces`, then `node scripts/contract.mjs` for its name and keys in
|
|
46
|
+
`EventContract`; `EventEmitter` (`emit…`) with those, and for an appearance event the `AppearanceDispatcher.Sender`.
|
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
# The native screens `npx apex-navigation codegen` lists in the app: the navigation finds the list by its name.
|
|
2
2
|
-keep class dev.apexnative.navigation.generated.ApexNavigationGeneratedScreens { *; }
|
|
3
|
+
|
|
4
|
+
# The library's C++ measures a React root's content through the surface's handler, which it reads by this getter's
|
|
5
|
+
# name (`android/src/main/jni/ANNContentHeights.cpp`).
|
|
6
|
+
-keepclassmembers class com.facebook.react.runtime.ReactSurfaceImpl {
|
|
7
|
+
com.facebook.react.fabric.SurfaceHandlerBinding getSurfaceHandler();
|
|
8
|
+
}
|
|
@@ -11,6 +11,7 @@ import android.view.View
|
|
|
11
11
|
import android.view.ViewGroup
|
|
12
12
|
import android.view.ViewTreeObserver
|
|
13
13
|
import android.widget.EditText
|
|
14
|
+
import androidx.activity.BackEventCompat
|
|
14
15
|
import androidx.activity.OnBackPressedCallback
|
|
15
16
|
import androidx.activity.SystemBarStyle
|
|
16
17
|
import androidx.activity.enableEdgeToEdge as enableActivityEdgeToEdge
|
|
@@ -34,9 +35,12 @@ import dev.apexnative.navigation.splash.SplashTheme
|
|
|
34
35
|
import dev.apexnative.navigation.splash.SplashView
|
|
35
36
|
import dev.apexnative.navigation.system.SystemUiWindow
|
|
36
37
|
import dev.apexnative.navigation.utils.MaterialTheme
|
|
38
|
+
import dev.apexnative.navigation.viewcontrollers.modal.SheetBack
|
|
39
|
+
import dev.apexnative.navigation.viewcontrollers.navigator.BackCallbackCheck
|
|
37
40
|
import dev.apexnative.navigation.viewcontrollers.navigator.BackCallbackState
|
|
38
41
|
import dev.apexnative.navigation.viewcontrollers.navigator.Navigator
|
|
39
42
|
import dev.apexnative.navigation.viewcontrollers.navigator.Navigators
|
|
43
|
+
import dev.apexnative.navigation.viewcontrollers.stack.StackController
|
|
40
44
|
|
|
41
45
|
/**
|
|
42
46
|
* The activity of an app with the navigation: its content holds, bottom to top, the copy of the splash and the layers
|
|
@@ -67,14 +71,75 @@ open class NavigationActivity : AppCompatActivity(), DefaultHardwareBackBtnHandl
|
|
|
67
71
|
private val reloadBroadcast = ReloadBroadcast(this) { reloadFromDeveloperTools() }
|
|
68
72
|
|
|
69
73
|
// Enabled while back has something to do in the app (BackCallbackState); otherwise the system does its own back.
|
|
74
|
+
// From Android 14, where the app hears the progress of the back gesture, a gesture that would pop a stack with the
|
|
75
|
+
// default transition previews the pop as the system previews back between activities (`StackController
|
|
76
|
+
// .BackGesture`), and one that would dismiss a sheet previews its hide as Material's sheets do (`SheetBack`), its
|
|
77
|
+
// release closing it as a drag down does; JavaScript's listeners hear back first, so with them there is no preview.
|
|
70
78
|
private val backCallback = object : OnBackPressedCallback(false) {
|
|
71
|
-
override fun
|
|
79
|
+
override fun handleOnBackStarted(backEvent: BackEventCompat) {
|
|
80
|
+
backGesture = null
|
|
81
|
+
sheetGesture = null
|
|
82
|
+
val navigator = navigator ?: return
|
|
83
|
+
backCheck?.atBack(navigator)
|
|
84
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE || BackCallbackState.hasJsListeners) return
|
|
85
|
+
val stack = navigator.stackPoppedByBack()
|
|
86
|
+
if (stack != null) {
|
|
87
|
+
backGesture = stack.startBackGesture(backEvent.swipeEdge == BackEventCompat.EDGE_LEFT, backEvent.touchY)
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
sheetGesture = navigator.sheetDismissedByBack()?.startBackPreview(backEvent)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
override fun handleOnBackProgressed(backEvent: BackEventCompat) {
|
|
94
|
+
backGesture?.progress(backEvent.progress, backEvent.touchY)
|
|
95
|
+
sheetGesture?.progress(backEvent)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
override fun handleOnBackCancelled() {
|
|
99
|
+
backGesture?.cancel()
|
|
100
|
+
backGesture = null
|
|
101
|
+
sheetGesture?.cancel()
|
|
102
|
+
sheetGesture = null
|
|
103
|
+
navigator?.let(BackCallbackState::update)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
override fun handleOnBackPressed() {
|
|
107
|
+
navigator?.let { backCheck?.atBack(it) }
|
|
108
|
+
val gesture = backGesture
|
|
109
|
+
backGesture = null
|
|
110
|
+
val sheet = sheetGesture
|
|
111
|
+
sheetGesture = null
|
|
112
|
+
when {
|
|
113
|
+
gesture?.commit() == true -> BackCallbackState.update()
|
|
114
|
+
sheet != null && commitSheet(sheet) -> BackCallbackState.update()
|
|
115
|
+
else -> passBack()
|
|
116
|
+
}
|
|
117
|
+
}
|
|
72
118
|
}
|
|
73
119
|
|
|
74
|
-
//
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
120
|
+
// The back gesture that previews a pop now; none.
|
|
121
|
+
private var backGesture: StackController.BackGesture? = null
|
|
122
|
+
|
|
123
|
+
// The back gesture that previews a sheet's hide now; none.
|
|
124
|
+
private var sheetGesture: SheetBack.Gesture? = null
|
|
125
|
+
|
|
126
|
+
// A sheet's preview released: the sheet goes as the user's drag down closes it, and back doesn't go on (no
|
|
127
|
+
// `passBack`, which would dismiss it a second time). A command that changed what back does since the gesture
|
|
128
|
+
// started (a push in the sheet, a modal over it, a hold) leaves it to the usual back, the sheet back in place.
|
|
129
|
+
private fun commitSheet(gesture: SheetBack.Gesture): Boolean {
|
|
130
|
+
if (navigator?.sheetDismissedByBack() !== gesture.sheet) {
|
|
131
|
+
gesture.cancel()
|
|
132
|
+
return false
|
|
133
|
+
}
|
|
134
|
+
return gesture.commit()
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Debug builds only: the check that what back does never changes without its trigger (BackCallbackState), sampled
|
|
138
|
+
// before frames and at back events. It only logs; release builds have neither the check nor the listener.
|
|
139
|
+
private val backCheck = if (BuildConfig.DEBUG) BackCallbackCheck() else null
|
|
140
|
+
private val backCheckBeforeFrame = ViewTreeObserver.OnPreDrawListener {
|
|
141
|
+
val navigator = navigator
|
|
142
|
+
if (navigator != null) backCheck?.sample(navigator, SystemClock.uptimeMillis())
|
|
78
143
|
true
|
|
79
144
|
}
|
|
80
145
|
private var frameObserver: ViewTreeObserver? = null
|
|
@@ -115,7 +180,9 @@ open class NavigationActivity : AppCompatActivity(), DefaultHardwareBackBtnHandl
|
|
|
115
180
|
SlotHost.attachIfStarted(this)
|
|
116
181
|
reactGateway.onActivityCreated(this)
|
|
117
182
|
onBackPressedDispatcher.addCallback(this, backCallback)
|
|
118
|
-
|
|
183
|
+
if (backCheck != null) {
|
|
184
|
+
frameObserver = window.decorView.viewTreeObserver.also { it.addOnPreDrawListener(backCheckBeforeFrame) }
|
|
185
|
+
}
|
|
119
186
|
// The activity's system UI: its owner remembers the theme's colors and the manifest's orientation now, before
|
|
120
187
|
// anything changes them.
|
|
121
188
|
navigator.systemUi.start(SystemUiWindow.of(this))
|
|
@@ -190,6 +257,8 @@ open class NavigationActivity : AppCompatActivity(), DefaultHardwareBackBtnHandl
|
|
|
190
257
|
isNavigationResumed = true
|
|
191
258
|
// The root, the modals and the overlays lay out again; nothing is sent.
|
|
192
259
|
navigator?.onResume()
|
|
260
|
+
// A safety net: what back does changes on its own triggers, and the system asks the callback from here on.
|
|
261
|
+
navigator?.let(BackCallbackState::update)
|
|
193
262
|
if (developerSupport() != null) reloadBroadcast.register()
|
|
194
263
|
ReloadCoordinator.launchIfDue(this)
|
|
195
264
|
}
|
|
@@ -211,6 +280,8 @@ open class NavigationActivity : AppCompatActivity(), DefaultHardwareBackBtnHandl
|
|
|
211
280
|
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
|
212
281
|
super.onWindowFocusChanged(hasFocus)
|
|
213
282
|
if (reactGateway.currentReactContext != null) reactGateway.host.onWindowFocusChange(hasFocus)
|
|
283
|
+
// A safety net, as at onResume: back after a dialog or another window over the activity.
|
|
284
|
+
if (hasFocus) navigator?.let(BackCallbackState::update)
|
|
214
285
|
}
|
|
215
286
|
|
|
216
287
|
override fun onUserLeaveHint() {
|
|
@@ -274,9 +345,11 @@ open class NavigationActivity : AppCompatActivity(), DefaultHardwareBackBtnHandl
|
|
|
274
345
|
splashHold = null
|
|
275
346
|
reloadBroadcast.release()
|
|
276
347
|
navigator?.let(BackCallbackState::detach)
|
|
277
|
-
// The window's observer now, and the one
|
|
278
|
-
|
|
279
|
-
|
|
348
|
+
// The debug check's listener: from the window's observer now, and the one it was added to, if they differ.
|
|
349
|
+
if (backCheck != null) {
|
|
350
|
+
val observers = listOfNotNull(frameObserver, window?.peekDecorView()?.viewTreeObserver).distinct()
|
|
351
|
+
observers.forEach { if (it.isAlive) it.removeOnPreDrawListener(backCheckBeforeFrame) }
|
|
352
|
+
}
|
|
280
353
|
frameObserver = null
|
|
281
354
|
SlotHost.detach(this)
|
|
282
355
|
navigator?.destroyWithActivity()
|
|
@@ -289,7 +362,9 @@ open class NavigationActivity : AppCompatActivity(), DefaultHardwareBackBtnHandl
|
|
|
289
362
|
/**
|
|
290
363
|
* Back that JavaScript's listeners didn't take: the navigation does its step first — a stack's top leaves or holds,
|
|
291
364
|
* a pane closes —; with nothing to do there, the activity's own back, as without the navigation. An app may
|
|
292
|
-
* override it (e.g. `moveTaskToBack(true)`).
|
|
365
|
+
* override it (e.g. `moveTaskToBack(true)`). The callback is off for that back only: the dispatcher's own back is
|
|
366
|
+
* the activity's, not [onBackPressed]; then it is computed again, and `hardwareBackButton.systemAnimation: false`
|
|
367
|
+
* turns it on again.
|
|
293
368
|
*/
|
|
294
369
|
override fun invokeDefaultOnBackPressed() {
|
|
295
370
|
val handled = navigator?.handleBack(CommandListenerAdapter()) == true
|
|
@@ -3,32 +3,49 @@ package dev.apexnative.navigation
|
|
|
3
3
|
import android.app.Application
|
|
4
4
|
import android.util.Log
|
|
5
5
|
import com.facebook.react.ReactApplication
|
|
6
|
-
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint
|
|
7
|
-
import com.facebook.react.soloader.OpenSourceMergedSoMapping
|
|
8
6
|
import com.facebook.soloader.SoLoader
|
|
9
7
|
import dev.apexnative.navigation.nativescreen.NativeScreenCreator
|
|
10
8
|
import dev.apexnative.navigation.react.ReactGateway
|
|
11
9
|
import dev.apexnative.navigation.utils.NavigationLog
|
|
12
10
|
|
|
13
11
|
/**
|
|
14
|
-
* The application class of an app with the navigation: it
|
|
15
|
-
*
|
|
16
|
-
*
|
|
12
|
+
* The application class of an app with the navigation: it keeps one React host for every screen ([reactGateway]) and
|
|
13
|
+
* the native screens by name. The app gives the host (`reactHost`) and loads React Native in its `onCreate` as the
|
|
14
|
+
* React Native template does, so the load follows the app's Gradle settings (the New Architecture, edge-to-edge):
|
|
15
|
+
*
|
|
16
|
+
* ```kotlin
|
|
17
|
+
* override fun onCreate() {
|
|
18
|
+
* super.onCreate()
|
|
19
|
+
* loadReactNative(this)
|
|
20
|
+
* registerNativeScreen("Profile") { activity, context -> ProfileView(activity, context) }
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* The gateway, and with it the host, is made the first time something needs it (the first activity), after the app's
|
|
25
|
+
* `onCreate` loaded React Native.
|
|
17
26
|
*/
|
|
18
27
|
abstract class NavigationApplication : Application(), ReactApplication {
|
|
19
28
|
// Written on the main thread as the app registers, read on the module thread by the layout checks: under its lock.
|
|
20
29
|
private val nativeScreens = LinkedHashMap<String, NativeScreenCreator>()
|
|
21
30
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
31
|
+
// Made once, by the first activity ([reactGateway]); [reactGatewayOrNull] only reads it.
|
|
32
|
+
private val gateway: Lazy<ReactGateway> = lazy {
|
|
33
|
+
check(SoLoader.isInitialized()) {
|
|
34
|
+
"NavigationApplication needs React Native loaded first: call loadReactNative(this) in onCreate, " +
|
|
35
|
+
"as the React Native template does"
|
|
36
|
+
}
|
|
37
|
+
createReactGateway()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The app's React host as the navigation runs it, made when it is first asked for (the first activity's
|
|
42
|
+
* `onCreate`). React Native must be loaded by then: the app calls `loadReactNative(this)` in its `onCreate`.
|
|
43
|
+
*/
|
|
44
|
+
val reactGateway: ReactGateway by gateway
|
|
25
45
|
|
|
26
46
|
override fun onCreate() {
|
|
27
47
|
super.onCreate()
|
|
28
48
|
instance = this
|
|
29
|
-
SoLoader.init(this, OpenSourceMergedSoMapping)
|
|
30
|
-
DefaultNewArchitectureEntryPoint.load()
|
|
31
|
-
reactGateway = createReactGateway()
|
|
32
49
|
registerGeneratedScreens()
|
|
33
50
|
}
|
|
34
51
|
|
|
@@ -57,9 +74,13 @@ abstract class NavigationApplication : Application(), ReactApplication {
|
|
|
57
74
|
internal fun isNativeScreenRegistered(name: String): Boolean =
|
|
58
75
|
synchronized(nativeScreens) { nativeScreens.containsKey(name) }
|
|
59
76
|
|
|
60
|
-
/**
|
|
77
|
+
/**
|
|
78
|
+
* [reactGateway] once the first activity made it; none before. It never makes it: its callers (the log, the
|
|
79
|
+
* events, a React root) may run first, also off the main thread, and the app's `reactHost` isn't theirs to make.
|
|
80
|
+
* Any thread.
|
|
81
|
+
*/
|
|
61
82
|
internal val reactGatewayOrNull: ReactGateway?
|
|
62
|
-
get() = if (
|
|
83
|
+
get() = if (gateway.isInitialized()) gateway.value else null
|
|
63
84
|
|
|
64
85
|
// The list of `npx apex-navigation codegen`, found by its name: an app without native screens has none.
|
|
65
86
|
private fun registerGeneratedScreens() {
|
|
@@ -47,5 +47,9 @@ internal object LayoutChecks {
|
|
|
47
47
|
*/
|
|
48
48
|
@JvmStatic
|
|
49
49
|
fun checkStackChild(node: LayoutNode, stackId: String): String? =
|
|
50
|
-
if (node
|
|
50
|
+
if (isStackChild(node)) null else ErrorTexts.stackTakesScreens(stackId, node.type.jsName)
|
|
51
|
+
|
|
52
|
+
/** Whether a stack takes [node]: a screen, a native screen or a pair, not a container. */
|
|
53
|
+
@JvmStatic
|
|
54
|
+
fun isStackChild(node: LayoutNode): Boolean = node.type in stackChildren
|
|
51
55
|
}
|
|
@@ -82,10 +82,14 @@ internal data class LayoutNode(
|
|
|
82
82
|
private val COLUMN_NAMES = setOf(PRIMARY, SECONDARY, SUPPLEMENTARY, COMPACT, INSPECTOR)
|
|
83
83
|
private val COLUMNS_WITHOUT_NAMES = listOf(PRIMARY, SECONDARY)
|
|
84
84
|
|
|
85
|
-
/**
|
|
85
|
+
/**
|
|
86
|
+
* The column of the child at [index] of a split view with [columns]; none for a child without one, and none
|
|
87
|
+
* for a repeat of a name an earlier child has (the first takes the column), as on iOS.
|
|
88
|
+
*/
|
|
86
89
|
internal fun columnName(columns: List<String>, index: Int): String? {
|
|
87
90
|
val names = columns.ifEmpty { COLUMNS_WITHOUT_NAMES }
|
|
88
|
-
|
|
91
|
+
val name = names.getOrNull(index)?.takeIf { it in COLUMN_NAMES } ?: return null
|
|
92
|
+
return name.takeIf { names.indexOf(it) == index }
|
|
89
93
|
}
|
|
90
94
|
}
|
|
91
95
|
}
|
|
@@ -44,8 +44,8 @@ class NativeScreenContext @RestrictTo(RestrictTo.Scope.LIBRARY) constructor(
|
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* Runs a command of the navigation from this screen in JS, as `useNavigation()` of a React screen does: push, pop,
|
|
47
|
-
* popTo, popToRoot, showInColumn, showModal, dismiss, showOverlay,
|
|
48
|
-
*
|
|
47
|
+
* popTo, popToRoot, showInColumn, showModal, dismiss, showOverlay, setOptions, selectTab, setTabBadge.
|
|
48
|
+
* [arguments] are those of the JS command; [result] gets what it resolved with.
|
|
49
49
|
*/
|
|
50
50
|
@JvmOverloads
|
|
51
51
|
fun navigate(command: String, arguments: JSONArray = JSONArray(), result: ((Result<Any?>) -> Unit)? = null) =
|
|
@@ -8,7 +8,7 @@ import com.facebook.react.bridge.ReadableMap
|
|
|
8
8
|
*/
|
|
9
9
|
class AnimationsOptions {
|
|
10
10
|
@JvmField var push = StackPushAnimationOptions()
|
|
11
|
-
@JvmField var pop =
|
|
11
|
+
@JvmField var pop = StackPopAnimationOptions()
|
|
12
12
|
@JvmField var setStackRoot = SetStackRootAnimationOptions()
|
|
13
13
|
@JvmField var setRoot = EnterExitAnimationOptions()
|
|
14
14
|
@JvmField var showModal = ModalAnimationOptions()
|
|
@@ -43,7 +43,7 @@ class AnimationsOptions {
|
|
|
43
43
|
val options = AnimationsOptions()
|
|
44
44
|
if (map == null) return options
|
|
45
45
|
options.push = map.group("push") { StackPushAnimationOptions.parse(it) }
|
|
46
|
-
options.pop = map.group("pop") {
|
|
46
|
+
options.pop = map.group("pop") { StackPopAnimationOptions.parse(it) }
|
|
47
47
|
options.setStackRoot = map.group("setStackRoot") { SetStackRootAnimationOptions.parse(it) }
|
|
48
48
|
options.setRoot = map.group("setRoot") { EnterExitAnimationOptions.parse(it) }
|
|
49
49
|
options.showModal = map.group("showModal") { ModalAnimationOptions.parse(it) }
|
|
@@ -105,7 +105,7 @@ class BottomTabOptions {
|
|
|
105
105
|
@JvmField var textColor: ThemeColour = NullThemeColour()
|
|
106
106
|
@JvmField var selectedIconColor: ThemeColour = NullThemeColour()
|
|
107
107
|
@JvmField var selectedTextColor: ThemeColour = NullThemeColour()
|
|
108
|
-
@JvmField var font = FontOptions()
|
|
108
|
+
@ReadFromParent @JvmField var font = FontOptions()
|
|
109
109
|
@JvmField var fontSize: Fraction = NullFraction()
|
|
110
110
|
@JvmField var selectedFontSize: Fraction = NullFraction()
|
|
111
111
|
@JvmField var iconInsets = IconInsetsOptions()
|
|
@@ -95,6 +95,7 @@ class BottomTabsAccessoryOptions {
|
|
|
95
95
|
class BottomTabsOptions {
|
|
96
96
|
@JvmField var visible: Bool = NullBool()
|
|
97
97
|
@JvmField var animate: Bool = NullBool()
|
|
98
|
+
@JvmField var switchAnimation: Text = NullText()
|
|
98
99
|
/** Selects a tab once; a whole number, truncated where it is read. */
|
|
99
100
|
@JvmField var currentTabIndex: Fraction = NullFraction()
|
|
100
101
|
/** Selects a tab once. */
|
|
@@ -124,18 +125,19 @@ class BottomTabsOptions {
|
|
|
124
125
|
@JvmField var minimizeBehavior: Text = NullText()
|
|
125
126
|
@JvmField var bottomAccessory = BottomTabsAccessoryOptions()
|
|
126
127
|
|
|
127
|
-
fun hasValue(): Boolean = visible.hasValue() || animate.hasValue() ||
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
bottomAccessory.hasValue()
|
|
128
|
+
fun hasValue(): Boolean = visible.hasValue() || animate.hasValue() || switchAnimation.hasValue() ||
|
|
129
|
+
currentTabIndex.hasValue() || currentTabId.hasValue() || testID.hasValue() || accessibilityLabel.hasValue() ||
|
|
130
|
+
moreTestID.hasValue() || drawBehind.hasValue() || backgroundColor.hasValue() || tabsAttachMode.hasValue() ||
|
|
131
|
+
barStyle.hasValue() || layoutStyle.hasValue() || cornerRadius.hasValue() || bottomMargin.hasValue() ||
|
|
132
|
+
translucent.hasValue() || hideShadow.hasValue() || titleDisplayMode.hasValue() || elevation.hasValue() ||
|
|
133
|
+
hideOnScroll.hasValue() || borderColor.hasValue() || borderWidth.hasValue() || shadow.hasValue() ||
|
|
134
|
+
customRow.hasValue() || sidebar.hasValue() || sidebarLayout.hasValue() || customizationId.hasValue() ||
|
|
135
|
+
minimizeBehavior.hasValue() || bottomAccessory.hasValue()
|
|
135
136
|
|
|
136
137
|
fun mergeWith(other: BottomTabsOptions) {
|
|
137
138
|
if (other.visible.hasValue()) visible = other.visible
|
|
138
139
|
if (other.animate.hasValue()) animate = other.animate
|
|
140
|
+
if (other.switchAnimation.hasValue()) switchAnimation = other.switchAnimation
|
|
139
141
|
if (other.currentTabIndex.hasValue()) currentTabIndex = other.currentTabIndex
|
|
140
142
|
if (other.currentTabId.hasValue()) currentTabId = other.currentTabId
|
|
141
143
|
if (other.testID.hasValue()) testID = other.testID
|
|
@@ -167,6 +169,7 @@ class BottomTabsOptions {
|
|
|
167
169
|
fun mergeWithDefault(defaults: BottomTabsOptions) {
|
|
168
170
|
if (!visible.hasValue()) visible = defaults.visible
|
|
169
171
|
if (!animate.hasValue()) animate = defaults.animate
|
|
172
|
+
if (!switchAnimation.hasValue()) switchAnimation = defaults.switchAnimation
|
|
170
173
|
if (!currentTabIndex.hasValue()) currentTabIndex = defaults.currentTabIndex
|
|
171
174
|
if (!currentTabId.hasValue()) currentTabId = defaults.currentTabId
|
|
172
175
|
if (!testID.hasValue()) testID = defaults.testID
|
|
@@ -198,6 +201,7 @@ class BottomTabsOptions {
|
|
|
198
201
|
fun copy() = BottomTabsOptions().also { it.mergeWith(this) }
|
|
199
202
|
|
|
200
203
|
companion object {
|
|
204
|
+
private val SWITCH_ANIMATIONS = setOf("platform", "none")
|
|
201
205
|
private val TABS_ATTACH_MODES = setOf("together", "afterInitialTab", "onSwitchToTab")
|
|
202
206
|
private val BAR_STYLES = setOf("default", "black")
|
|
203
207
|
private val LAYOUT_STYLES = setOf("stretch", "compact")
|
|
@@ -212,6 +216,7 @@ class BottomTabsOptions {
|
|
|
212
216
|
if (map == null) return options
|
|
213
217
|
options.visible = BoolParser.parse(map, "visible")
|
|
214
218
|
options.animate = BoolParser.parse(map, "animate")
|
|
219
|
+
options.switchAnimation = TextParser.parse(map, "switchAnimation", SWITCH_ANIMATIONS)
|
|
215
220
|
options.currentTabIndex = FractionParser.parse(map, "currentTabIndex")
|
|
216
221
|
options.currentTabId = TextParser.parse(map, "currentTabId")
|
|
217
222
|
options.testID = TextParser.parse(map, "testID")
|
|
@@ -8,8 +8,8 @@ import dev.apexnative.navigation.options.parsers.IconParser
|
|
|
8
8
|
* A menu of the bar: `topBar.overflowMenu`, or the `menu` of a button. Its items, and submenus among them; with
|
|
9
9
|
* `singleSelection` one item of a level has a checkmark at a time.
|
|
10
10
|
*
|
|
11
|
-
* Copied options share it, so
|
|
12
|
-
*
|
|
11
|
+
* Copied options share it, so nobody changes a menu in place but in a copy of its own: the check a user's pick moves
|
|
12
|
+
* lives in the screen's user layer (`UserChoices`), which goes into a copy as the screen's options resolve.
|
|
13
13
|
*/
|
|
14
14
|
class ButtonMenuOptions(
|
|
15
15
|
@JvmField val singleSelection: Boolean,
|
|
@@ -31,7 +31,7 @@ class ButtonOptions(@JvmField var id: Text = NullText()) {
|
|
|
31
31
|
@JvmField var systemItem: Text = NullText()
|
|
32
32
|
@JvmField var text: Text = NullText()
|
|
33
33
|
@JvmField var accessibilityLabel: Text = NullText()
|
|
34
|
-
@JvmField var font = FontOptions()
|
|
34
|
+
@ReadFromParent @JvmField var font = FontOptions()
|
|
35
35
|
@JvmField var fontSize: Fraction = NullFraction()
|
|
36
36
|
@JvmField var enabled: Bool = NullBool()
|
|
37
37
|
@JvmField var disableIconTint: Bool = NullBool()
|
|
@@ -197,8 +197,8 @@ class ButtonOptions(@JvmField var id: Text = NullText()) {
|
|
|
197
197
|
|
|
198
198
|
/**
|
|
199
199
|
* A copy of the menu with new items and submenus and the same values. A menu taken from the default options is copied
|
|
200
|
-
* first, so that
|
|
201
|
-
* own and resolved options share the menu
|
|
200
|
+
* first, so that nothing written into a resolved result reaches [DefaultOptions.current]; the user layer writes its
|
|
201
|
+
* checks into a copy too (`UserChoices`), and copies between a node's own and resolved options share the menu.
|
|
202
202
|
*/
|
|
203
203
|
internal fun ButtonMenuOptions.copyMenu(): ButtonMenuOptions =
|
|
204
204
|
ButtonMenuOptions(singleSelection, items.map(::copyElement), testID)
|