@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
|
@@ -3,13 +3,14 @@ package dev.apexnative.navigation.react
|
|
|
3
3
|
import android.util.Log
|
|
4
4
|
import com.facebook.react.bridge.Promise
|
|
5
5
|
import dev.apexnative.navigation.react.events.EventEmitter
|
|
6
|
-
import dev.apexnative.navigation.react.events.
|
|
6
|
+
import dev.apexnative.navigation.react.events.NavigationState
|
|
7
7
|
import dev.apexnative.navigation.utils.NavigationLog
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* The one answer of a command with a promise: [resolve] or [reject], once; after that, and once the JavaScript it came
|
|
11
|
-
* from went ([generation]), nothing.
|
|
12
|
-
* a [CommandListener] answers through [asListener]. Main
|
|
11
|
+
* from went ([generation]), nothing. It owns the command's one state step ([reportStateNow]). [CommandRunner] makes it
|
|
12
|
+
* on the main thread for each command; area code that takes a [CommandListener] answers through [asListener]. Main
|
|
13
|
+
* thread only.
|
|
13
14
|
*/
|
|
14
15
|
internal class CommandAnswer(
|
|
15
16
|
/** The method of the command: `push`, `setRoot`, … */
|
|
@@ -27,22 +28,39 @@ internal class CommandAnswer(
|
|
|
27
28
|
var isAnswered = false
|
|
28
29
|
private set
|
|
29
30
|
|
|
31
|
+
// The state step of this answer ran ([reportStateNow]).
|
|
32
|
+
private var stateReported = false
|
|
33
|
+
|
|
30
34
|
/** Whether an answer now would reach the JavaScript the command came from. */
|
|
31
35
|
val canAnswer: Boolean
|
|
32
36
|
get() = !isAnswered && ReloadCoordinator.isCurrent(generation)
|
|
33
37
|
|
|
34
38
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
39
|
+
* The navigation state now, sent when it changed, once per answer: the end of the command's transition asks for it
|
|
40
|
+
* after the DidAppear it sends and before the transition's own events (`AppearanceDispatcher.endTransition`);
|
|
41
|
+
* otherwise [resolve] asks for it before the promise. A later call sends nothing, and nothing goes for a JavaScript
|
|
42
|
+
* that went. A failure of the step is logged and costs only the state.
|
|
43
|
+
*/
|
|
44
|
+
fun reportStateNow() {
|
|
45
|
+
if (stateReported) return
|
|
46
|
+
stateReported = true
|
|
47
|
+
if (!ReloadCoordinator.isCurrent(generation)) return
|
|
48
|
+
guarded("report the navigation state") { events.stateNow() }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Resolves the promise with [value]. For the commands that change what shows (`CommandContract.STATE`), the
|
|
53
|
+
* navigation state goes first, when it changed and the command's transition didn't send it already
|
|
54
|
+
* ([reportStateNow]), so JavaScript has it when its `await` goes on; `ANN.CommandCompleted` follows the promise,
|
|
55
|
+
* for the commands that show or dismiss. A failure of either is logged; the promise goes all the same.
|
|
38
56
|
*/
|
|
39
57
|
fun resolve(value: Any?) {
|
|
40
58
|
if (!canAnswer) return
|
|
41
59
|
isAnswered = true
|
|
42
|
-
if (commandName in
|
|
60
|
+
if (commandName in CommandContract.STATE) reportStateNow()
|
|
43
61
|
promise.resolve(value)
|
|
44
62
|
val commandId = commandId
|
|
45
|
-
if (commandName in
|
|
63
|
+
if (commandName in CommandContract.COMPLETED && commandId != null) {
|
|
46
64
|
guarded("send ANN.CommandCompleted") { events.commandCompleted(commandName, commandId, clock()) }
|
|
47
65
|
}
|
|
48
66
|
}
|
|
@@ -65,44 +83,19 @@ internal class CommandAnswer(
|
|
|
65
83
|
log("[ApexNavigation] $commandName: ${ErrorTexts.couldNot(what, ErrorTexts.reasonOf(e))}")
|
|
66
84
|
}
|
|
67
85
|
}
|
|
68
|
-
|
|
69
|
-
companion object {
|
|
70
|
-
// The commands that send `ANN.CommandCompleted` (EVT-CommandCompleted).
|
|
71
|
-
val COMPLETED_COMMANDS = setOf(
|
|
72
|
-
"setRoot",
|
|
73
|
-
"push",
|
|
74
|
-
"pop",
|
|
75
|
-
"popTo",
|
|
76
|
-
"popToRoot",
|
|
77
|
-
"setStackRoot",
|
|
78
|
-
"showInColumn",
|
|
79
|
-
"showModal",
|
|
80
|
-
"dismissModal",
|
|
81
|
-
"dismissAllModals",
|
|
82
|
-
"showOverlay",
|
|
83
|
-
"dismissOverlay",
|
|
84
|
-
"dismissAllOverlays",
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
// The commands whose answer comes after the navigation state: those and `setColumnShown`.
|
|
88
|
-
val STATE_COMMANDS = COMPLETED_COMMANDS + "setColumnShown"
|
|
89
|
-
}
|
|
90
86
|
}
|
|
91
87
|
|
|
92
88
|
/** What goes to JavaScript around the answer of a command. Main thread only. */
|
|
93
89
|
internal interface AnswerEvents {
|
|
94
|
-
/**
|
|
95
|
-
fun
|
|
90
|
+
/** The answer's one state step ([CommandAnswer.reportStateNow]): the navigation state now, when it changed. */
|
|
91
|
+
fun stateNow()
|
|
96
92
|
|
|
97
93
|
/** After the promise resolved: `ANN.CommandCompleted`. */
|
|
98
94
|
fun commandCompleted(commandName: String, commandId: String, completionTime: Long)
|
|
99
95
|
|
|
100
96
|
/** Through the sender of the JavaScript that runs now. */
|
|
101
97
|
object Current : AnswerEvents {
|
|
102
|
-
override fun
|
|
103
|
-
val emitter = EventEmitter.current()
|
|
104
|
-
if (emitter.canSend) NavigationStateReporter.updateNow(emitter)
|
|
105
|
-
}
|
|
98
|
+
override fun stateNow() = NavigationState.updateNow()
|
|
106
99
|
|
|
107
100
|
override fun commandCompleted(commandName: String, commandId: String, completionTime: Long) {
|
|
108
101
|
EventEmitter.current().emitCommandCompleted(commandName, commandId, completionTime)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Made by scripts/contract.mjs from src/interfaces/contract/commands.json: change that file and run the script again.
|
|
2
|
+
|
|
3
|
+
package dev.apexnative.navigation.react
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* What the commands with a promise answer, the same table as iOS. What each resolves with:
|
|
7
|
+
* - `setRoot`: the id of the root, once the root and the layout's modals and overlays show.
|
|
8
|
+
* - `push`: the id of the screen that shows; of a pair, the pair's id.
|
|
9
|
+
* - `preparePush`: the frame `{ width, height, padding }` of the prepared screen, or null; always null on iOS.
|
|
10
|
+
* - `pop`: the id of the screen that went.
|
|
11
|
+
* - `popTo`: the id of the screen it went back to.
|
|
12
|
+
* - `popToRoot`: the id of the first screen of the stack.
|
|
13
|
+
* - `setStackRoot`: the id of the new top screen.
|
|
14
|
+
* - `showModal`: the id of the modal's root.
|
|
15
|
+
* - `dismissModal`: the id of the modal's root.
|
|
16
|
+
* - `dismissAllModals`: an empty string.
|
|
17
|
+
* - `showOverlay`: the id of the overlay's root.
|
|
18
|
+
* - `dismissOverlay`: the id of the overlay's root.
|
|
19
|
+
* - `dismissAllOverlays`: an empty string.
|
|
20
|
+
* - `showInColumn`: the id of the screen that shows.
|
|
21
|
+
* - `setColumnShown`: nothing once the columns stopped moving (`undefined` on iOS, `null` on Android).
|
|
22
|
+
* - `getLaunchLink`: the link that launched the app, or null.
|
|
23
|
+
*/
|
|
24
|
+
internal object CommandContract {
|
|
25
|
+
/** The commands whose answer comes after the navigation state: every one that may change what shows. */
|
|
26
|
+
val STATE: Set<String> = setOf(
|
|
27
|
+
"setRoot",
|
|
28
|
+
"push",
|
|
29
|
+
"pop",
|
|
30
|
+
"popTo",
|
|
31
|
+
"popToRoot",
|
|
32
|
+
"setStackRoot",
|
|
33
|
+
"showModal",
|
|
34
|
+
"dismissModal",
|
|
35
|
+
"dismissAllModals",
|
|
36
|
+
"showOverlay",
|
|
37
|
+
"dismissOverlay",
|
|
38
|
+
"dismissAllOverlays",
|
|
39
|
+
"showInColumn",
|
|
40
|
+
"setColumnShown",
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
/** The commands that send `ANN.CommandCompleted` after their answer: every one that shows or dismisses. */
|
|
44
|
+
val COMPLETED: Set<String> = setOf(
|
|
45
|
+
"setRoot",
|
|
46
|
+
"push",
|
|
47
|
+
"pop",
|
|
48
|
+
"popTo",
|
|
49
|
+
"popToRoot",
|
|
50
|
+
"setStackRoot",
|
|
51
|
+
"showModal",
|
|
52
|
+
"dismissModal",
|
|
53
|
+
"dismissAllModals",
|
|
54
|
+
"showOverlay",
|
|
55
|
+
"dismissOverlay",
|
|
56
|
+
"dismissAllOverlays",
|
|
57
|
+
"showInColumn",
|
|
58
|
+
)
|
|
59
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
package dev.apexnative.navigation.react
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import com.facebook.react.interfaces.fabric.ReactSurface
|
|
6
|
+
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
|
|
7
|
+
import com.facebook.react.modules.i18nmanager.I18nUtil
|
|
8
|
+
import com.facebook.react.runtime.ReactSurfaceImpl
|
|
9
|
+
import com.facebook.soloader.SoLoader
|
|
10
|
+
import dev.apexnative.navigation.utils.NavigationLog
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The height of React content laid out at a width without a height limit, as iOS measures a sheet's `'content'`
|
|
14
|
+
* detent: Fabric lays out a copy of the tree, so the shown layout stays as it is. A React root's surface measures
|
|
15
|
+
* through `SurfaceHandler::measure`; a slot's content in the slot's own layout, once asked for ([requestSlot]), which
|
|
16
|
+
* keeps the height for [slotHeight] (`ANNSlotContentHeights`, the C++ iOS shares). The native half is the library's
|
|
17
|
+
* own C++ (`android/src/main/jni`), in the codegen library of its components; when that library doesn't load, nothing
|
|
18
|
+
* is measured. Main thread.
|
|
19
|
+
*/
|
|
20
|
+
internal object ContentHeights {
|
|
21
|
+
private const val LIBRARY = "react_codegen_ApexNavigationSpec"
|
|
22
|
+
|
|
23
|
+
private val loaded: Boolean by lazy {
|
|
24
|
+
try {
|
|
25
|
+
SoLoader.loadLibrary(LIBRARY)
|
|
26
|
+
true
|
|
27
|
+
} catch (e: Throwable) {
|
|
28
|
+
Log.w(NavigationLog.TAG, "[ApexNavigation] $LIBRARY doesn't load: no content is measured", e)
|
|
29
|
+
false
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The height of [surface]'s content at [width] pixels, in pixels, with the layout context the surface lays out
|
|
35
|
+
* with (`ReactSurfaceImpl.updateLayoutSpecs`); null before the surface runs or renders, or when it can't measure.
|
|
36
|
+
*/
|
|
37
|
+
fun surfaceHeight(context: Context, surface: ReactSurface, width: Int): Int? {
|
|
38
|
+
if (width <= 0 || surface !is ReactSurfaceImpl || !loaded) return null
|
|
39
|
+
val density = context.resources.displayMetrics.density
|
|
40
|
+
val scalesFont = ReactNativeFeatureFlags.enableFontScaleChangesUpdatingLayout()
|
|
41
|
+
val fontScale = if (scalesFont) context.resources.configuration.fontScale else 1f
|
|
42
|
+
val height = try {
|
|
43
|
+
nativeSurfaceHeight(
|
|
44
|
+
surface,
|
|
45
|
+
width / density,
|
|
46
|
+
density,
|
|
47
|
+
fontScale,
|
|
48
|
+
I18nUtil.instance.isRTL(context),
|
|
49
|
+
I18nUtil.instance.doLeftAndRightSwapInRTL(context),
|
|
50
|
+
)
|
|
51
|
+
} catch (e: Throwable) {
|
|
52
|
+
Log.w(NavigationLog.TAG, "[ApexNavigation] the content of a surface can't be measured", e)
|
|
53
|
+
return null
|
|
54
|
+
}
|
|
55
|
+
return if (height > 0f) Math.round(height * density) else null
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** The content of the slot [slotId] is measured from its next layout on. */
|
|
59
|
+
fun requestSlot(slotId: String) {
|
|
60
|
+
if (loaded) nativeRequestSlot(slotId)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** The content of the slot [slotId] is measured. */
|
|
64
|
+
fun isSlotRequested(slotId: String): Boolean = loaded && nativeIsSlotRequested(slotId)
|
|
65
|
+
|
|
66
|
+
/** The height of the content of the slot [slotId] at its last layout, in dp; null before it. */
|
|
67
|
+
fun slotHeight(slotId: String): Float? = if (loaded) nativeSlotHeight(slotId).takeIf { it >= 0f } else null
|
|
68
|
+
|
|
69
|
+
/** The screen of the slot [slotId] went: nothing more is measured for it. */
|
|
70
|
+
fun forgetSlot(slotId: String) {
|
|
71
|
+
if (loaded) nativeForgetSlot(slotId)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@JvmStatic
|
|
75
|
+
private external fun nativeRequestSlot(slotId: String)
|
|
76
|
+
|
|
77
|
+
@JvmStatic
|
|
78
|
+
private external fun nativeIsSlotRequested(slotId: String): Boolean
|
|
79
|
+
|
|
80
|
+
@JvmStatic
|
|
81
|
+
private external fun nativeSlotHeight(slotId: String): Float
|
|
82
|
+
|
|
83
|
+
@JvmStatic
|
|
84
|
+
private external fun nativeForgetSlot(slotId: String)
|
|
85
|
+
|
|
86
|
+
@JvmStatic
|
|
87
|
+
private external fun nativeSurfaceHeight(
|
|
88
|
+
surface: ReactSurfaceImpl,
|
|
89
|
+
width: Float,
|
|
90
|
+
pointScale: Float,
|
|
91
|
+
fontScale: Float,
|
|
92
|
+
rtl: Boolean,
|
|
93
|
+
swapLeftAndRight: Boolean,
|
|
94
|
+
): Float
|
|
95
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
package dev.apexnative.navigation.react
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.UIManager
|
|
4
|
+
import com.facebook.react.bridge.UIManagerListener
|
|
5
|
+
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
|
6
|
+
import com.facebook.react.uimanager.UIManagerHelper
|
|
7
|
+
import com.facebook.react.uimanager.common.UIManagerType
|
|
8
|
+
import dev.apexnative.navigation.NavigationApplication
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The handlers of a screen's content that hear each mount of Fabric (`IReactView.setOnContentMounted`), by key, while
|
|
12
|
+
* [hears] holds (the content is in a window and not destroyed). Fabric tells every mount of the app, on the main
|
|
13
|
+
* thread, not those of one surface: the handlers measure and compare, so a mount elsewhere costs only that. It listens
|
|
14
|
+
* only while a handler waits. Main thread only.
|
|
15
|
+
*/
|
|
16
|
+
internal class ContentMounts(private val hears: () -> Boolean) {
|
|
17
|
+
private val handlers = LinkedHashMap<String, Runnable>()
|
|
18
|
+
// The UI manager that tells the mounts; none while no handler waits.
|
|
19
|
+
private var uiManager: UIManager? = null
|
|
20
|
+
|
|
21
|
+
// React Native marks the listener unstable; it is the one place that tells a mount.
|
|
22
|
+
@OptIn(UnstableReactNativeAPI::class)
|
|
23
|
+
private val listener = object : UIManagerListener {
|
|
24
|
+
override fun willDispatchViewUpdates(uiManager: UIManager) = Unit
|
|
25
|
+
|
|
26
|
+
override fun willMountItems(uiManager: UIManager) = Unit
|
|
27
|
+
|
|
28
|
+
override fun didMountItems(uiManager: UIManager) {
|
|
29
|
+
if (hears()) run()
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
override fun didDispatchMountItems(uiManager: UIManager) = Unit
|
|
33
|
+
|
|
34
|
+
override fun didScheduleMountItems(uiManager: UIManager) = Unit
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** [handler] runs after each mount under [key]; null removes the handler of [key]. */
|
|
38
|
+
fun set(key: String, handler: Runnable?) {
|
|
39
|
+
if (handler == null) handlers.remove(key) else handlers[key] = handler
|
|
40
|
+
if (handlers.isEmpty()) stop() else start()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Runs the handlers now: a mount the content tells itself. */
|
|
44
|
+
fun run() = handlers.values.toList().forEach(Runnable::run)
|
|
45
|
+
|
|
46
|
+
/** The content goes: no handler runs again. */
|
|
47
|
+
fun clear() {
|
|
48
|
+
handlers.clear()
|
|
49
|
+
stop()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@OptIn(UnstableReactNativeAPI::class)
|
|
53
|
+
private fun start() {
|
|
54
|
+
if (uiManager != null) return
|
|
55
|
+
val reactContext = NavigationApplication.instanceOrNull?.reactGatewayOrNull?.currentReactContext ?: return
|
|
56
|
+
uiManager = UIManagerHelper.getUIManager(reactContext, UIManagerType.FABRIC)?.also {
|
|
57
|
+
it.addUIManagerEventListener(listener)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@OptIn(UnstableReactNativeAPI::class)
|
|
62
|
+
private fun stop() {
|
|
63
|
+
uiManager?.removeUIManagerEventListener(listener)
|
|
64
|
+
uiManager = null
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// Made by scripts/contract.mjs from src/interfaces/contract/errors.json: change that file and run the script again.
|
|
2
|
+
|
|
1
3
|
package dev.apexnative.navigation.react
|
|
2
4
|
|
|
3
5
|
/**
|
|
@@ -6,116 +8,129 @@ package dev.apexnative.navigation.react
|
|
|
6
8
|
* <command>:`.
|
|
7
9
|
*/
|
|
8
10
|
internal object ErrorTexts {
|
|
9
|
-
|
|
11
|
+
// Where the screen is.
|
|
12
|
+
|
|
13
|
+
fun screenNotShown(componentId: String) = "the screen '$componentId' is not shown"
|
|
10
14
|
|
|
11
|
-
fun notInStack(
|
|
15
|
+
fun notInStack(componentId: String) = "the screen '$componentId' is not in a stack"
|
|
12
16
|
|
|
13
|
-
fun firstScreenOfStack(
|
|
17
|
+
fun firstScreenOfStack(componentId: String) = "the screen '$componentId' is the first screen of its stack"
|
|
14
18
|
|
|
15
|
-
fun notInThisStack(
|
|
19
|
+
fun notInThisStack(componentId: String) = "the screen '$componentId' is not in this stack"
|
|
16
20
|
|
|
17
|
-
fun notInModal(
|
|
21
|
+
fun notInModal(componentId: String) = "the screen '$componentId' is not in a modal"
|
|
18
22
|
|
|
19
|
-
fun notInOverlay(
|
|
23
|
+
fun notInOverlay(componentId: String) = "the screen '$componentId' is not in an overlay"
|
|
20
24
|
|
|
21
|
-
fun notInSplitView(
|
|
25
|
+
fun notInSplitView(componentId: String) = "the screen '$componentId' is not in a split view"
|
|
22
26
|
|
|
23
|
-
fun neitherSplitViewNorStack(
|
|
27
|
+
fun neitherSplitViewNorStack(componentId: String) =
|
|
28
|
+
"the screen '$componentId' is neither in a split view nor in a stack"
|
|
24
29
|
|
|
25
|
-
fun noSuchColumn(
|
|
30
|
+
fun noSuchColumn(componentId: String, column: String) =
|
|
31
|
+
"the split view of the screen '$componentId' has no '$column' column"
|
|
26
32
|
|
|
27
|
-
fun columnIsStack(
|
|
28
|
-
"the '$column' column of the split view of the screen '$
|
|
33
|
+
fun columnIsStack(componentId: String, column: String) =
|
|
34
|
+
"the '$column' column of the split view of the screen '$componentId' is a stack: it takes a screen, not a stack"
|
|
29
35
|
|
|
30
|
-
fun columnNotStack(
|
|
31
|
-
"the '$column' column of the split view of the screen '$
|
|
36
|
+
fun columnNotStack(componentId: String, column: String) =
|
|
37
|
+
"the '$column' column of the split view of the screen '$componentId' is not a stack"
|
|
32
38
|
|
|
33
|
-
fun noScreensForStack(
|
|
39
|
+
fun noScreensForStack(componentId: String) = "there are no screens to put in the stack of the screen '$componentId'"
|
|
34
40
|
|
|
35
|
-
fun alreadyShown(
|
|
41
|
+
fun alreadyShown(componentId: String) = "the screen '$componentId' shows already: an id goes to one screen"
|
|
36
42
|
|
|
37
|
-
|
|
38
|
-
"setRoot was replaced by a newer setRoot before the root '$id' finished showing"
|
|
43
|
+
// Root, modals, the app.
|
|
39
44
|
|
|
40
|
-
fun
|
|
45
|
+
fun setRootReplaced(rootId: String) =
|
|
46
|
+
"setRoot was replaced by a newer setRoot before the root '$rootId' finished showing"
|
|
41
47
|
|
|
42
|
-
fun
|
|
48
|
+
fun rootDestroyed(rootId: String) = "the root '$rootId' was destroyed before it showed"
|
|
49
|
+
|
|
50
|
+
fun modalWithoutRoot(componentId: String) = "the modal '$componentId' can't be dismissed: there is no root under it"
|
|
43
51
|
|
|
44
52
|
fun nowhereToShow() = "the navigation has nowhere to show screens: the app has no activity or window"
|
|
45
53
|
|
|
54
|
+
// Native screens.
|
|
55
|
+
|
|
46
56
|
fun nativeScreenNotRegistered(name: String) = "no native screen is registered as '$name'"
|
|
47
57
|
|
|
48
58
|
fun nativeScreenNotCreated(name: String) =
|
|
49
59
|
"the native screen '$name' could not be created: its creator returned nothing"
|
|
50
60
|
|
|
51
|
-
|
|
61
|
+
/** The error of a call of a native screen whose JavaScript reloaded before it answered. */
|
|
62
|
+
fun nativeCallReloaded(name: String, componentId: String) =
|
|
63
|
+
"JavaScript reloaded before the call '$name' of the screen '$componentId' was answered"
|
|
52
64
|
|
|
53
|
-
|
|
65
|
+
/** The error of a call of a native screen while no JavaScript can answer it. */
|
|
66
|
+
fun nativeCallNotRunning(name: String, componentId: String) =
|
|
67
|
+
"the navigation is not running: the call '$name' of the screen '$componentId' can't be answered"
|
|
54
68
|
|
|
55
|
-
|
|
56
|
-
"the side menu '$id' has a child of type '$type': it takes SideMenuLeft, SideMenuCenter and SideMenuRight"
|
|
69
|
+
// The layout.
|
|
57
70
|
|
|
58
|
-
fun
|
|
71
|
+
fun unknownNodeType(type: String) = "the layout has a node of unknown type '$type'"
|
|
59
72
|
|
|
60
|
-
fun
|
|
73
|
+
fun nodeWithoutId(type: String) = "the layout has a node of type '$type' without an id"
|
|
61
74
|
|
|
62
|
-
fun
|
|
75
|
+
fun sideMenuChild(menuId: String, type: String) =
|
|
76
|
+
"the side menu '$menuId' has a child of type '$type': it takes SideMenuLeft, SideMenuCenter and SideMenuRight"
|
|
63
77
|
|
|
64
|
-
fun
|
|
78
|
+
fun stackTakesScreens(stackId: String, type: String) = "the stack '$stackId' takes screens, not a '$type'"
|
|
65
79
|
|
|
66
|
-
fun
|
|
80
|
+
fun emptyStack(stackId: String) = "the stack '$stackId' has no screens"
|
|
67
81
|
|
|
68
|
-
fun
|
|
82
|
+
fun emptyTabs(tabsId: String) = "the tabs '$tabsId' have no tabs"
|
|
69
83
|
|
|
70
|
-
|
|
84
|
+
/** Only Android checks it: its tab bar shows at most 5 tabs. */
|
|
85
|
+
fun tooManyTabs(tabsId: String, count: Int) = "the tabs '$tabsId' have $count tabs: Android shows at most 5"
|
|
71
86
|
|
|
72
|
-
fun
|
|
73
|
-
"the
|
|
87
|
+
fun splitViewColumns(splitViewId: String) =
|
|
88
|
+
"the split view '$splitViewId' needs its primary and its secondary column"
|
|
74
89
|
|
|
75
|
-
/**
|
|
76
|
-
fun
|
|
77
|
-
"the option '$path' of the default options has a value the navigation can't read"
|
|
90
|
+
/** Only iOS checks it: Android has pairs on every version. */
|
|
91
|
+
fun pairUnsupported(pairId: String) = "the pair '$pairId' needs iOS 27.1 and an app built with its SDK"
|
|
78
92
|
|
|
79
|
-
fun
|
|
93
|
+
fun pairNeedsTwoScreens(pairId: String) = "the pair '$pairId' needs two screens: its primary and its secondary"
|
|
80
94
|
|
|
81
|
-
|
|
82
|
-
fun couldNot(what: String, reason: String) = "could not $what: $reason"
|
|
95
|
+
fun nodeWithoutName(type: String, nodeId: String) = "the layout has a node '$nodeId' of type '$type' without a name"
|
|
83
96
|
|
|
84
|
-
fun
|
|
85
|
-
"JavaScript reloaded before the call '$name' of the screen '$id' was answered"
|
|
97
|
+
fun rootMissing() = "the layout of setRoot has no root"
|
|
86
98
|
|
|
87
|
-
fun
|
|
88
|
-
"the navigation is not running: the call '$name' of the screen '$id' can't be answered"
|
|
99
|
+
fun tabsInTabs(tabsId: String) = "the tabs '$tabsId' have a tab of type 'BottomTabs': tabs don't go inside tabs"
|
|
89
100
|
|
|
90
|
-
|
|
91
|
-
|
|
101
|
+
fun sideMenuSides(menuId: String) =
|
|
102
|
+
"the side menu '$menuId' takes one SideMenuCenter and at most one SideMenuLeft and one SideMenuRight"
|
|
92
103
|
|
|
93
|
-
|
|
94
|
-
|
|
104
|
+
fun sideChildCount(sideId: String, menuId: String) =
|
|
105
|
+
"the side '$sideId' of the side menu '$menuId' needs exactly one child"
|
|
95
106
|
|
|
96
|
-
|
|
107
|
+
fun sideMenuInSide(menuId: String) =
|
|
108
|
+
"the side menu '$menuId' has a side menu in a side: a side menu doesn't go inside a side menu"
|
|
97
109
|
|
|
98
|
-
fun
|
|
110
|
+
fun sideOutsideMenu(nodeId: String, type: String) =
|
|
111
|
+
"the layout has a node '$nodeId' of type '$type' outside a side menu"
|
|
99
112
|
|
|
100
|
-
fun
|
|
113
|
+
fun splitViewInColumn(splitViewId: String) =
|
|
114
|
+
"the split view '$splitViewId' has a column of type 'SplitView': a split view doesn't go inside a split view"
|
|
101
115
|
|
|
102
|
-
fun
|
|
116
|
+
fun idGivenTwice(nodeId: String) = "the layout gives the id '$nodeId' to two nodes"
|
|
103
117
|
|
|
104
|
-
|
|
105
|
-
"the side menu '$id' takes one SideMenuCenter and at most one SideMenuLeft and one SideMenuRight"
|
|
118
|
+
// Options, previews, any other failure.
|
|
106
119
|
|
|
107
|
-
fun
|
|
108
|
-
"the
|
|
120
|
+
fun unreadableOption(path: String, componentId: String) =
|
|
121
|
+
"the option '$path' of the screen '$componentId' has a value the navigation can't read"
|
|
109
122
|
|
|
110
|
-
|
|
111
|
-
|
|
123
|
+
/** An unreadable value of `setDefaultOptions`: the default options belong to no screen. */
|
|
124
|
+
fun unreadableDefaultOption(path: String) =
|
|
125
|
+
"the option '$path' of the default options has a value the navigation can't read"
|
|
112
126
|
|
|
113
|
-
fun
|
|
127
|
+
fun previewGone(previewId: String) = "the preview '$previewId' went without being opened"
|
|
114
128
|
|
|
115
|
-
|
|
116
|
-
|
|
129
|
+
/** Any other failure: what could not be done and why, `could not <what>: <reason>`. */
|
|
130
|
+
fun couldNot(what: String, reason: String) = "could not $what: $reason"
|
|
117
131
|
|
|
118
|
-
|
|
132
|
+
/** A command whose part of the native core is not written yet. */
|
|
133
|
+
fun notDoneYet(method: String) = "could not run '$method': the native core doesn't do it yet"
|
|
119
134
|
|
|
120
135
|
/** The reason of [couldNot] for an exception: its message, else the name of its class. */
|
|
121
136
|
fun reasonOf(e: Throwable): String =
|
|
@@ -9,26 +9,32 @@ import android.os.Build
|
|
|
9
9
|
import androidx.lifecycle.DefaultLifecycleObserver
|
|
10
10
|
import androidx.lifecycle.Lifecycle
|
|
11
11
|
import androidx.lifecycle.LifecycleOwner
|
|
12
|
-
import com.facebook.react.ReactApplication
|
|
13
12
|
import com.facebook.react.bridge.Arguments
|
|
14
13
|
import com.facebook.react.bridge.WritableMap
|
|
14
|
+
import dev.apexnative.navigation.react.events.EventContract
|
|
15
15
|
import dev.apexnative.navigation.react.events.EventEmitter
|
|
16
16
|
import dev.apexnative.navigation.utils.WindowFolds
|
|
17
17
|
import java.lang.ref.WeakReference
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* The device's hinge (`useHinge`): its state from the fold in the activity's window, its angle from the hinge angle
|
|
21
|
-
* sensor (Android 11+). Android has no public state of a closed device: closed is a
|
|
22
|
-
* angle under 90
|
|
23
|
-
* (`setHingeUpdates`), the sensor only while the activity is resumed too; the same value
|
|
24
|
-
*
|
|
21
|
+
* sensor (Android 11+), in degrees to a tenth as on iOS. Android has no public state of a closed device: closed is a
|
|
22
|
+
* window without a fold, or an angle under 90° ([valueOf]). No sensor and no fold: no hinge, `{}`. It runs while
|
|
23
|
+
* JavaScript has a hook mounted (`setHingeUpdates`), the sensor only while the activity is resumed too; the same value
|
|
24
|
+
* is not sent twice. The values go to the JavaScript that turned the updates on (`EventEmitter.current` then): after a
|
|
25
|
+
* reload, until the updates stop, they go nowhere. Main thread only, but [get].
|
|
25
26
|
*/
|
|
26
27
|
internal object Hinge {
|
|
27
|
-
|
|
28
|
+
/** A value of the hinge: its state, and its angle in degrees to a tenth; none while the state is unknown. */
|
|
29
|
+
data class Value(val state: String, val angle: Double?)
|
|
30
|
+
|
|
31
|
+
private const val UNKNOWN = "unknown"
|
|
28
32
|
|
|
29
33
|
private const val CLOSED_BELOW = 90f
|
|
30
34
|
|
|
31
35
|
private var enabled = false
|
|
36
|
+
// The sender of the JavaScript that turned the updates on; none while they are off.
|
|
37
|
+
private var emitter: EventEmitter? = null
|
|
32
38
|
private var activity: WeakReference<Activity>? = null
|
|
33
39
|
private var folds: WindowFolds? = null
|
|
34
40
|
private var sensorManager: SensorManager? = null
|
|
@@ -59,9 +65,11 @@ internal object Hinge {
|
|
|
59
65
|
fun setEnabled(activity: Activity?, enabled: Boolean) {
|
|
60
66
|
this.enabled = enabled
|
|
61
67
|
if (!enabled) {
|
|
68
|
+
emitter = null
|
|
62
69
|
detach()
|
|
63
70
|
return
|
|
64
71
|
}
|
|
72
|
+
emitter = EventEmitter.current()
|
|
65
73
|
activity?.let(::attachTo)
|
|
66
74
|
update()
|
|
67
75
|
}
|
|
@@ -127,28 +135,32 @@ internal object Hinge {
|
|
|
127
135
|
if (!enabled) return
|
|
128
136
|
val folds = folds ?: return
|
|
129
137
|
if (!folds.hasInfo || (listening && angle == null)) return
|
|
130
|
-
val
|
|
131
|
-
val angle = angle
|
|
132
|
-
val value = if (fold == null && sensor == null) {
|
|
133
|
-
null
|
|
134
|
-
} else {
|
|
135
|
-
val state = when {
|
|
136
|
-
fold?.halfOpened == true -> "partiallyOpen"
|
|
137
|
-
fold != null -> "fullyOpen"
|
|
138
|
-
angle != null && angle < CLOSED_BELOW -> "closed"
|
|
139
|
-
else -> "unknown"
|
|
140
|
-
}
|
|
141
|
-
Value(state, angle)
|
|
142
|
-
}
|
|
138
|
+
val value = valueOf(folds.folds.firstOrNull(), sensor != null, angle)
|
|
143
139
|
if (value == last) return
|
|
144
140
|
last = value
|
|
145
|
-
|
|
146
|
-
|
|
141
|
+
emitter?.emitHingeChanged(toMap(value))
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* The value of the window's first [fold] and the sensor's [angle]: none without a fold and without a sensor
|
|
146
|
+
* ([hasSensor]). `closed` without a fold or under 90°, else `partiallyOpen` for a half-opened fold and `fullyOpen`
|
|
147
|
+
* for a flat one. The angle goes to a tenth, as iOS gives it: the sensor's noise doesn't make a new value, and it
|
|
148
|
+
* is left out while the state is unknown.
|
|
149
|
+
*/
|
|
150
|
+
fun valueOf(fold: WindowFolds.Fold?, hasSensor: Boolean, angle: Float?): Value? {
|
|
151
|
+
if (fold == null && !hasSensor) return null
|
|
152
|
+
val state = when {
|
|
153
|
+
fold == null || (angle != null && angle < CLOSED_BELOW) -> "closed"
|
|
154
|
+
fold.halfOpened -> "partiallyOpen"
|
|
155
|
+
else -> "fullyOpen"
|
|
156
|
+
}
|
|
157
|
+
val tenths = angle?.let { Math.round(it * 10.0) / 10.0 }
|
|
158
|
+
return Value(state, tenths.takeIf { state != UNKNOWN })
|
|
147
159
|
}
|
|
148
160
|
|
|
149
161
|
private fun toMap(value: Value?): WritableMap = Arguments.createMap().apply {
|
|
150
162
|
if (value == null) return@apply
|
|
151
|
-
putString(
|
|
152
|
-
value.angle?.let { putDouble(
|
|
163
|
+
putString(EventContract.HingeChanged.STATE, value.state)
|
|
164
|
+
if (value.state != UNKNOWN) value.angle?.let { putDouble(EventContract.HingeChanged.ANGLE, it) }
|
|
153
165
|
}
|
|
154
166
|
}
|