@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
|
@@ -55,6 +55,10 @@ class NavigationTurboModule(reactContext: ReactApplicationContext) : NativeANNTu
|
|
|
55
55
|
override fun mergeOptions(componentId: String, options: ReadableMap) =
|
|
56
56
|
optionsCommands.mergeOptions(componentId, options)
|
|
57
57
|
|
|
58
|
+
// Development (Fast Refresh): the options an edit took out of a screen that shows; as mergeOptions without one.
|
|
59
|
+
override fun clearOptions(componentId: String, paths: ReadableArray) =
|
|
60
|
+
optionsCommands.clearOptions(componentId, paths)
|
|
61
|
+
|
|
58
62
|
override fun push(commandId: String, componentId: String, layout: ReadableMap, promise: Promise) {
|
|
59
63
|
val what = "push the screen '${LayoutReader.idOf(layout)}'"
|
|
60
64
|
runner.run(
|
|
@@ -211,7 +215,7 @@ class NavigationTurboModule(reactContext: ReactApplicationContext) : NativeANNTu
|
|
|
211
215
|
layout: ReadableMap,
|
|
212
216
|
promise: Promise,
|
|
213
217
|
) {
|
|
214
|
-
// Android
|
|
218
|
+
// Android's split view has the primary and the secondary pane; another column rejects (`showInColumn`).
|
|
215
219
|
val what = "show the screen '${LayoutReader.idOf(layout)}' in the '$column' column"
|
|
216
220
|
runner.run(
|
|
217
221
|
name = "showInColumn",
|
|
@@ -219,7 +223,7 @@ class NavigationTurboModule(reactContext: ReactApplicationContext) : NativeANNTu
|
|
|
219
223
|
what = what,
|
|
220
224
|
promise = promise,
|
|
221
225
|
check = { LayoutReader.node(layout, context = appContext()) },
|
|
222
|
-
) { node, answer -> navigator().stackCommands.showInColumn(componentId, node, answer, what) }
|
|
226
|
+
) { node, answer -> navigator().stackCommands.showInColumn(componentId, column, node, answer, what) }
|
|
223
227
|
}
|
|
224
228
|
|
|
225
229
|
override fun setColumnShown(
|
|
@@ -236,11 +240,11 @@ class NavigationTurboModule(reactContext: ReactApplicationContext) : NativeANNTu
|
|
|
236
240
|
check = {},
|
|
237
241
|
) { _, answer -> navigator().stackCommands.setColumnShown(componentId, column, shown, answer) }
|
|
238
242
|
|
|
239
|
-
override fun getArrangementState(componentId: String): WritableMap =
|
|
243
|
+
override fun getArrangementState(componentId: String): WritableMap = ScreenEnvironment.getArrangementState(componentId)
|
|
240
244
|
|
|
241
|
-
override fun getScreenInsets(componentId: String): WritableMap =
|
|
245
|
+
override fun getScreenInsets(componentId: String): WritableMap = ScreenEnvironment.getScreenInsets(componentId)
|
|
242
246
|
|
|
243
|
-
override fun getScreenRegions(componentId: String): WritableMap =
|
|
247
|
+
override fun getScreenRegions(componentId: String): WritableMap = ScreenEnvironment.getScreenRegions(componentId)
|
|
244
248
|
|
|
245
249
|
// With the activity the user sees, if there is one; the hinge remembers it and goes on with the next activity
|
|
246
250
|
// (`Hinge.attach`).
|
|
@@ -295,9 +299,10 @@ class NavigationTurboModule(reactContext: ReactApplicationContext) : NativeANNTu
|
|
|
295
299
|
})
|
|
296
300
|
}
|
|
297
301
|
|
|
298
|
-
// The navigation of the activity the command runs in; the runner checked there is
|
|
302
|
+
// The navigation of the activity the command runs in; the runner checked there is an activity. One without its
|
|
303
|
+
// navigation yet (or any more) has nowhere to show screens either: the command rejects with the runner's own text.
|
|
299
304
|
private fun navigator(): Navigator =
|
|
300
|
-
|
|
305
|
+
Navigators.current()?.navigator ?: throw LayoutException(ErrorTexts.nowhereToShow())
|
|
301
306
|
|
|
302
307
|
// The app's context, which the colors of the options resolve platform colors with.
|
|
303
308
|
private fun appContext(): Context = reactApplicationContext.applicationContext
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
package dev.apexnative.navigation.react
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
|
+
import com.facebook.react.bridge.ReadableArray
|
|
4
5
|
import com.facebook.react.bridge.ReadableMap
|
|
6
|
+
import com.facebook.react.bridge.ReadableType
|
|
5
7
|
import dev.apexnative.navigation.options.DefaultOptions
|
|
8
|
+
import dev.apexnative.navigation.options.OptionPaths
|
|
6
9
|
import dev.apexnative.navigation.options.Options
|
|
7
10
|
import dev.apexnative.navigation.options.OptionsReader
|
|
8
11
|
import dev.apexnative.navigation.system.AppDirection
|
|
@@ -10,9 +13,9 @@ import dev.apexnative.navigation.viewcontrollers.navigator.Navigators
|
|
|
10
13
|
import dev.apexnative.navigation.viewcontrollers.viewcontroller.ViewController
|
|
11
14
|
|
|
12
15
|
/**
|
|
13
|
-
* The commands of the options, `setDefaultOptions` and `
|
|
14
|
-
* on the module thread, in the runner's step before the main task; the main task stores
|
|
15
|
-
* read is logged (`[ApexNavigation] <method>: <text>`); the app goes on.
|
|
16
|
+
* The commands of the options, `setDefaultOptions`, `mergeOptions` and `clearOptions`: all without a promise. Their
|
|
17
|
+
* options and paths are read on the module thread, in the runner's step before the main task; the main task stores
|
|
18
|
+
* and applies them. What can't be read is logged (`[ApexNavigation] <method>: <text>`); the app goes on.
|
|
16
19
|
*/
|
|
17
20
|
internal class OptionsCommands(
|
|
18
21
|
private val runner: CommandRunner,
|
|
@@ -30,6 +33,11 @@ internal class OptionsCommands(
|
|
|
30
33
|
* system UI follows (`Navigator.optionsMerged`, `mergeOptions` step 5). Main thread.
|
|
31
34
|
*/
|
|
32
35
|
private val merged: (ViewController<*>, Options) -> Unit = { _, _ -> },
|
|
36
|
+
/**
|
|
37
|
+
* Repaints what shows in the current navigation activity, as [repaint] does without new default options
|
|
38
|
+
* (`Navigator.repaint`), after `clearOptions`. Main thread.
|
|
39
|
+
*/
|
|
40
|
+
private val repaintCurrent: () -> Unit = {},
|
|
33
41
|
) {
|
|
34
42
|
constructor(runner: CommandRunner, context: () -> Context?) : this(
|
|
35
43
|
runner = runner,
|
|
@@ -40,6 +48,7 @@ internal class OptionsCommands(
|
|
|
40
48
|
Navigators.all().forEach { it.navigator?.defaultOptionsChanged(direction) }
|
|
41
49
|
},
|
|
42
50
|
merged = { node, options -> Navigators.current()?.navigator?.optionsMerged(node, options) },
|
|
51
|
+
repaintCurrent = { Navigators.current()?.navigator?.repaint() },
|
|
43
52
|
)
|
|
44
53
|
|
|
45
54
|
/**
|
|
@@ -73,7 +82,7 @@ internal class OptionsCommands(
|
|
|
73
82
|
prepare = { OptionsReader.read(options, context()) },
|
|
74
83
|
) { read ->
|
|
75
84
|
if (!runner.hasActivity()) {
|
|
76
|
-
runner.logFailure(MERGE_OPTIONS, ErrorTexts.
|
|
85
|
+
runner.logFailure(MERGE_OPTIONS, ErrorTexts.nowhereToShow())
|
|
77
86
|
return@runVoid
|
|
78
87
|
}
|
|
79
88
|
val node = findNode(componentId) ?: return@runVoid
|
|
@@ -82,8 +91,37 @@ internal class OptionsCommands(
|
|
|
82
91
|
merged(node, read.options)
|
|
83
92
|
}
|
|
84
93
|
|
|
94
|
+
/**
|
|
95
|
+
* `clearOptions` (development: Fast Refresh, after an edit took options out of a screen that shows): the values at
|
|
96
|
+
* [paths] (`topBar.subtitle`; a group's path for the whole group) leave the own options of the node [componentId]
|
|
97
|
+
* names, through `ViewController.changeOptions` ([OptionPaths.clear]), so it resolves to what the layouts around it
|
|
98
|
+
* and the defaults give there; the user layer stays. The stack it is in writes its back arrow's visibility into
|
|
99
|
+
* them again (`StackController.ownOptionsCleared`), then what shows is repainted as after `setDefaultOptions`. No
|
|
100
|
+
* node with that id, or no path that names an option: nothing, not even a log line. Without an activity: one log
|
|
101
|
+
* line, as `mergeOptions`.
|
|
102
|
+
*/
|
|
103
|
+
fun clearOptions(componentId: String, paths: ReadableArray) = runner.runVoid(
|
|
104
|
+
name = CLEAR_OPTIONS,
|
|
105
|
+
what = "clear the options of the screen '$componentId'",
|
|
106
|
+
prepare = {
|
|
107
|
+
(0 until paths.size()).filter { paths.getType(it) == ReadableType.String }.mapNotNull(paths::getString)
|
|
108
|
+
},
|
|
109
|
+
) { read ->
|
|
110
|
+
if (!runner.hasActivity()) {
|
|
111
|
+
runner.logFailure(CLEAR_OPTIONS, ErrorTexts.nowhereToShow())
|
|
112
|
+
return@runVoid
|
|
113
|
+
}
|
|
114
|
+
val node = findNode(componentId) ?: return@runVoid
|
|
115
|
+
val known = read.filter { OptionPaths.find(node.options, it) != null }
|
|
116
|
+
if (known.isEmpty()) return@runVoid
|
|
117
|
+
node.changeOptions { own -> known.forEach { OptionPaths.clear(own, it) } }
|
|
118
|
+
node.findParentStack()?.ownOptionsCleared(node)
|
|
119
|
+
repaintCurrent()
|
|
120
|
+
}
|
|
121
|
+
|
|
85
122
|
private companion object {
|
|
86
123
|
const val SET_DEFAULT_OPTIONS = "setDefaultOptions"
|
|
87
124
|
const val MERGE_OPTIONS = "mergeOptions"
|
|
125
|
+
const val CLEAR_OPTIONS = "clearOptions"
|
|
88
126
|
}
|
|
89
127
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
package dev.apexnative.navigation.react
|
|
2
|
+
|
|
3
|
+
import dev.apexnative.navigation.NavigationApplication
|
|
4
|
+
import dev.apexnative.navigation.utils.UiThread
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The calls JavaScript made to the module that may not have reached the main thread yet: [after] runs a task on the
|
|
8
|
+
* main thread behind every one of them. A screen's first mount reaches the main thread from Fabric while a
|
|
9
|
+
* `mergeOptions` of the same React commit (its layout effects: `useScreenOptions`) may still be on its way: an
|
|
10
|
+
* asynchronous method goes from the JavaScript thread to the module's thread (`BridgelessNativeMethodCallInvoker`),
|
|
11
|
+
* which reads its options there and posts its body to the main thread ([CommandRunner]). The task goes the same way: a
|
|
12
|
+
* turn of the JavaScript thread, which comes after the task of the commit with its layout effects; then the module's
|
|
13
|
+
* thread, behind the calls that task made; then the main thread, behind their bodies. Each of the three runs its queue
|
|
14
|
+
* in order, so every call JavaScript made before the mount has applied when the task runs.
|
|
15
|
+
*
|
|
16
|
+
* Without JavaScript (none yet, a reload, a queue that ended) the task is posted to the main thread at once: nothing is
|
|
17
|
+
* on its way. A queue that ends while the task is on it drops it, and a wait with no limit of its own (a push with
|
|
18
|
+
* `waitForRender: true` whose content has mounted: the task is its only end) would not end; a queue ends only as the
|
|
19
|
+
* JavaScript goes (a reload, the host destroyed), and then the layouts go with it (`ReloadCoordinator`), the stack
|
|
20
|
+
* and its waiting push too. Main thread.
|
|
21
|
+
*/
|
|
22
|
+
internal object PendingCalls {
|
|
23
|
+
/** A queue the task goes through: it runs what it takes in order, and says false when it ended and took nothing. */
|
|
24
|
+
fun interface Queue {
|
|
25
|
+
fun run(task: Runnable): Boolean
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Runs [task] on the main thread, on a later turn, after every call JavaScript made so far has applied there. */
|
|
29
|
+
fun after(task: () -> Unit) {
|
|
30
|
+
val context = NavigationApplication.instanceOrNull?.reactGatewayOrNull?.currentReactContext
|
|
31
|
+
?.takeIf { it.hasActiveReactInstance() }
|
|
32
|
+
val js = context?.jsMessageQueueThread?.let { Queue(it::runOnQueue) }
|
|
33
|
+
val module = context?.nativeModulesMessageQueueThread?.let { Queue(it::runOnQueue) }
|
|
34
|
+
after(js, module, UiThread::post, task)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The way of [after] over the queues given: [js], then [module], then [main]; straight to [main] without one of
|
|
39
|
+
* them, or from where a queue refused it. The unit tests run it over their own queues.
|
|
40
|
+
*/
|
|
41
|
+
fun after(js: Queue?, module: Queue?, main: (Runnable) -> Unit, task: () -> Unit) {
|
|
42
|
+
val onMain = Runnable(task)
|
|
43
|
+
if (js == null || module == null) return main(onMain)
|
|
44
|
+
val toMain = Runnable { main(onMain) }
|
|
45
|
+
val toModule = Runnable { if (!module.run(toMain)) main(onMain) }
|
|
46
|
+
if (!js.run(toModule)) main(onMain)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -3,6 +3,7 @@ package dev.apexnative.navigation.react
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
4
|
import android.content.Context
|
|
5
5
|
import android.os.Bundle
|
|
6
|
+
import android.util.Size
|
|
6
7
|
import android.view.MotionEvent
|
|
7
8
|
import android.view.ViewGroup
|
|
8
9
|
import android.widget.FrameLayout
|
|
@@ -23,11 +24,17 @@ import dev.apexnative.navigation.viewcontrollers.viewcontroller.ScrollEventListe
|
|
|
23
24
|
* is made with the view, from the app's React host, and fills it; it starts once, as the view joins a window, and stops
|
|
24
25
|
* once, on the main thread, as the view is destroyed.
|
|
25
26
|
*
|
|
26
|
-
* Ready once the safe area view of the screen told [ScreenReadiness] that the content
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
27
|
+
* Ready once the safe area view of the screen, in this view's own surface, told [ScreenReadiness] that the content
|
|
28
|
+
* rendered into it: the signal of another root with the same id (an old one, another live root of a bar component)
|
|
29
|
+
* never makes this one ready. A screen without a safe area view (no view ever told anything of its id) is ready once
|
|
30
|
+
* the root view of its surface has children, read on this view's own layout passes. A root that renders at once
|
|
31
|
+
* ([rendersAtOnce]: a component of a bar, a tab's cell) marks its id so from before its surface starts until it stops.
|
|
32
|
+
* Ready once, ready for good; what waits for it ([whenReady]) runs then, once. Its content measures without a height
|
|
33
|
+
* limit ([contentSize], `ContentHeights`), and the handlers of [setOnContentMounted] hear each mount of Fabric while
|
|
34
|
+
* the view is in a window.
|
|
35
|
+
* Without a signal or children, the limits of what waits decide: the view has no timer of its own. It owns the
|
|
36
|
+
* record of its appearance, which the dispatcher of the appearance events holds until the content is ready
|
|
37
|
+
* (`AppearanceDispatcher`).
|
|
31
38
|
*/
|
|
32
39
|
@SuppressLint("ViewConstructor")
|
|
33
40
|
class ReactView @JvmOverloads constructor(
|
|
@@ -36,6 +43,8 @@ class ReactView @JvmOverloads constructor(
|
|
|
36
43
|
override val componentName: String,
|
|
37
44
|
/** Props given by the native side, over `componentId`: the state of a tab's cell. */
|
|
38
45
|
initialProps: Bundle? = null,
|
|
46
|
+
/** The root renders at once, without waiting for its layout: a component of a bar or a tab's cell. */
|
|
47
|
+
private val rendersAtOnce: Boolean = false,
|
|
39
48
|
) : FrameLayout(context), IReactView {
|
|
40
49
|
private val scrollEventListener = ScrollEventListener()
|
|
41
50
|
private var destroyed = false
|
|
@@ -44,7 +53,15 @@ class ReactView @JvmOverloads constructor(
|
|
|
44
53
|
// What waited for the readiness was told; a question of isReady alone tells nothing, so nothing runs inside it.
|
|
45
54
|
private var readyTold = false
|
|
46
55
|
private val readyListeners = mutableListOf<Runnable>()
|
|
47
|
-
private var
|
|
56
|
+
private var listening = false
|
|
57
|
+
private val mounts = ContentMounts { !destroyed && isAttachedToWindow }
|
|
58
|
+
|
|
59
|
+
// What this root hears of its id: only the signals of its own surface.
|
|
60
|
+
private val readiness = object : ScreenReadiness.Listener {
|
|
61
|
+
override fun accepts(source: Int): Boolean = ownSource()?.let { it == source } ?: true
|
|
62
|
+
|
|
63
|
+
override fun onContentRendered() = checkReadiness()
|
|
64
|
+
}
|
|
48
65
|
|
|
49
66
|
// None without the app's host (the unit tests).
|
|
50
67
|
private val surface: ReactSurface?
|
|
@@ -59,8 +76,17 @@ class ReactView @JvmOverloads constructor(
|
|
|
59
76
|
*/
|
|
60
77
|
internal var contentChildCount: () -> Int = { (surface?.view as? ViewGroup)?.childCount ?: 0 }
|
|
61
78
|
|
|
79
|
+
/**
|
|
80
|
+
* The id of this root's React surface, which the signals of its safe area view carry: React Native gives it as
|
|
81
|
+
* the surface starts (none matches before) and never gives it again. Null without a surface: every signal of the
|
|
82
|
+
* id is its own. The unit tests give their own.
|
|
83
|
+
*/
|
|
84
|
+
internal var ownSource: () -> Int? = { surface?.surfaceID }
|
|
85
|
+
|
|
62
86
|
init {
|
|
63
87
|
require(componentId.isNotEmpty()) { "a React root needs the id of its screen" }
|
|
88
|
+
// Before the surface exists, so its safe area view never asks before the mark is there.
|
|
89
|
+
if (rendersAtOnce) ScreenReadiness.setRendersAtOnce(componentId, this, true)
|
|
64
90
|
val props = Bundle().apply {
|
|
65
91
|
initialProps?.let(::putAll)
|
|
66
92
|
putString(COMPONENT_ID, componentId)
|
|
@@ -90,6 +116,16 @@ class ReactView @JvmOverloads constructor(
|
|
|
90
116
|
override val touchRoot: ViewGroup?
|
|
91
117
|
get() = surface?.view as? ViewGroup
|
|
92
118
|
|
|
119
|
+
override fun contentSize(maxWidth: Int): Size? {
|
|
120
|
+
val surface = surface ?: return null
|
|
121
|
+
val height = ContentHeights.surfaceHeight(context, surface, maxWidth) ?: return null
|
|
122
|
+
return Size(maxWidth, height)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
override fun setOnContentMounted(key: String, handler: Runnable?) {
|
|
126
|
+
if (!destroyed) mounts.set(key, handler)
|
|
127
|
+
}
|
|
128
|
+
|
|
93
129
|
override fun isReady(): Boolean {
|
|
94
130
|
if (!ready && hasRendered()) ready = true
|
|
95
131
|
return ready
|
|
@@ -103,14 +139,9 @@ class ReactView @JvmOverloads constructor(
|
|
|
103
139
|
if (readyTold) return listener.run()
|
|
104
140
|
readyListeners += listener
|
|
105
141
|
if (isReady()) return checkReadiness()
|
|
106
|
-
if (
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
override fun onContentRendered() = checkReadiness()
|
|
111
|
-
}
|
|
112
|
-
readinessListener = readiness
|
|
113
|
-
ScreenReadiness.setListener(componentId, readiness)
|
|
142
|
+
if (listening) return
|
|
143
|
+
listening = true
|
|
144
|
+
ScreenReadiness.addListener(componentId, this, readiness)
|
|
114
145
|
}
|
|
115
146
|
|
|
116
147
|
/**
|
|
@@ -126,30 +157,33 @@ class ReactView @JvmOverloads constructor(
|
|
|
126
157
|
waiting.forEach(Runnable::run)
|
|
127
158
|
}
|
|
128
159
|
|
|
129
|
-
// The safe area view said so; without one, the root view of the surface has children.
|
|
130
|
-
private fun hasRendered(): Boolean = when (ScreenReadiness.isContentRendered(componentId)) {
|
|
160
|
+
// The safe area view of this root's surface said so; without one, the root view of the surface has children.
|
|
161
|
+
private fun hasRendered(): Boolean = when (ScreenReadiness.isContentRendered(componentId, readiness)) {
|
|
131
162
|
true -> true
|
|
132
163
|
false -> false
|
|
133
164
|
null -> contentChildCount() > 0
|
|
134
165
|
}
|
|
135
166
|
|
|
136
167
|
private fun stopListening() {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
ScreenReadiness.removeListener(componentId,
|
|
168
|
+
if (!listening) return
|
|
169
|
+
listening = false
|
|
170
|
+
ScreenReadiness.removeListener(componentId, this)
|
|
140
171
|
}
|
|
141
172
|
|
|
142
173
|
/**
|
|
143
174
|
* Stops the content, once, on the main thread: its appearance ends first (DidDisappear if its WillAppear went,
|
|
144
175
|
* else what is held goes with it), then the surface stops and leaves the host, so a reload doesn't start it again
|
|
145
|
-
* in the new JavaScript.
|
|
176
|
+
* in the new JavaScript. A root that renders at once takes its mark away: the last one of its id takes what was
|
|
177
|
+
* said of the id with it.
|
|
146
178
|
*/
|
|
147
179
|
override fun destroy() {
|
|
148
180
|
if (destroyed) return
|
|
149
181
|
AppearanceDispatcher.didDisappear(appearance)
|
|
150
182
|
destroyed = true
|
|
151
183
|
readyListeners.clear()
|
|
184
|
+
mounts.clear()
|
|
152
185
|
stopListening()
|
|
186
|
+
if (rendersAtOnce) ScreenReadiness.setRendersAtOnce(componentId, this, false)
|
|
153
187
|
val surface = surface ?: return
|
|
154
188
|
if (started) surface.stop()
|
|
155
189
|
surface.detach()
|
|
@@ -4,7 +4,7 @@ import com.facebook.react.bridge.ReactContext
|
|
|
4
4
|
import dev.apexnative.navigation.NavigationActivity
|
|
5
5
|
import dev.apexnative.navigation.nativescreen.NativeScreenCalls
|
|
6
6
|
import dev.apexnative.navigation.react.events.EventEmitter
|
|
7
|
-
import dev.apexnative.navigation.react.events.
|
|
7
|
+
import dev.apexnative.navigation.react.events.NavigationState
|
|
8
8
|
import dev.apexnative.navigation.utils.UiThread
|
|
9
9
|
import dev.apexnative.navigation.viewcontrollers.navigator.BackCallbackState
|
|
10
10
|
import dev.apexnative.navigation.viewcontrollers.navigator.Navigator
|
|
@@ -39,7 +39,7 @@ internal object ReloadCoordinator {
|
|
|
39
39
|
/**
|
|
40
40
|
* The JavaScript goes (a reload, or the host is destroyed). Any thread: the number grows at once; the layouts of
|
|
41
41
|
* every navigation activity go on the main thread, with the "reloading" mark, and so do the listeners of the
|
|
42
|
-
* JavaScript that went (back, hinge).
|
|
42
|
+
* JavaScript that went (back, hinge) and the holds of the navigation state its `setRoot` left.
|
|
43
43
|
*/
|
|
44
44
|
fun onJavaScriptGoes() {
|
|
45
45
|
advance()
|
|
@@ -48,6 +48,7 @@ internal object ReloadCoordinator {
|
|
|
48
48
|
launches.contextGone()
|
|
49
49
|
try {
|
|
50
50
|
Navigators.all().forEach { it.onReload() }
|
|
51
|
+
NavigationState.javaScriptWent()
|
|
51
52
|
BackCallbackState.setJsListeners(false)
|
|
52
53
|
Hinge.setEnabled(Navigators.current(), false)
|
|
53
54
|
} finally {
|
|
@@ -59,13 +60,15 @@ internal object ReloadCoordinator {
|
|
|
59
60
|
/**
|
|
60
61
|
* The developer tools of [activity] reload the JavaScript ("R R", the reload broadcast): the number grows first, so
|
|
61
62
|
* the navigation of the activity goes without a word to the JavaScript that goes, then its layers go
|
|
62
|
-
* ([NavigationActivity.onReload]). The host's own reset follows as the
|
|
63
|
+
* ([NavigationActivity.onReload]) with the holds of the navigation state. The host's own reset follows as the
|
|
64
|
+
* reload destroys it. Main thread.
|
|
63
65
|
*/
|
|
64
66
|
fun resetForDeveloperReload(activity: NavigationActivity) {
|
|
65
67
|
advance()
|
|
66
68
|
Navigator.setReloading(true)
|
|
67
69
|
try {
|
|
68
70
|
activity.onReload()
|
|
71
|
+
NavigationState.javaScriptWent()
|
|
69
72
|
} finally {
|
|
70
73
|
Navigator.setReloading(false)
|
|
71
74
|
}
|
|
@@ -79,8 +82,6 @@ internal object ReloadCoordinator {
|
|
|
79
82
|
UiThread.runOnMain {
|
|
80
83
|
launches.contextReady(context)
|
|
81
84
|
NativeScreenCalls.failAll { name, componentId -> ErrorTexts.nativeCallReloaded(name, componentId) }
|
|
82
|
-
// Scroll listeners that found no event dispatcher listen now.
|
|
83
|
-
ScrollEvents.dispatcherReady()
|
|
84
85
|
Navigators.all().filter { it.isNavigationResumed }.forEach(::launchIfDue)
|
|
85
86
|
}
|
|
86
87
|
}
|
|
@@ -92,7 +93,7 @@ internal object ReloadCoordinator {
|
|
|
92
93
|
*/
|
|
93
94
|
fun launchIfDue(activity: NavigationActivity) {
|
|
94
95
|
val context = launches.takeDue(activity, activity.isNavigationResumed) ?: return
|
|
95
|
-
|
|
96
|
+
NavigationState.reset()
|
|
96
97
|
EventEmitter(context).emitAppLaunched()
|
|
97
98
|
}
|
|
98
99
|
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
package dev.apexnative.navigation.react
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.bridge.WritableArray
|
|
5
|
+
import com.facebook.react.bridge.WritableMap
|
|
6
|
+
import dev.apexnative.navigation.react.events.EventContract
|
|
7
|
+
import dev.apexnative.navigation.react.events.EventEmitter
|
|
8
|
+
import java.util.concurrent.ConcurrentHashMap
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* What JavaScript knows of each screen's place, by the screen's id, in one record: its safe area (the insets JavaScript
|
|
12
|
+
* gets and the padding of its safe area view, `useSafeAreaInsets`), its reserved regions (`useReservedRegions`) and,
|
|
13
|
+
* in a pair, its arrangement (`useArrangement`). The core measures them (`ScreenSafeArea`, [ScreenRegions], the pair's
|
|
14
|
+
* plan) on the main thread and keeps them here; JavaScript reads them from its own thread for a screen's first render
|
|
15
|
+
* and gets every change as an event. The record is immutable and replaced at once, so a reader on another thread sees
|
|
16
|
+
* one whole record. When the screen goes, [remove] clears all of it. As on iOS (`ANNScreenEnvironment`).
|
|
17
|
+
*/
|
|
18
|
+
internal object ScreenEnvironment {
|
|
19
|
+
/** How much covers each edge of a screen's content, in dp. */
|
|
20
|
+
data class Insets(val top: Double, val right: Double, val bottom: Double, val left: Double)
|
|
21
|
+
|
|
22
|
+
/** A reserved region, in dp from the top left of the screen's content. */
|
|
23
|
+
data class Region(val x: Double, val y: Double, val width: Double, val height: Double)
|
|
24
|
+
|
|
25
|
+
/** Where a screen divides (`division`) and where hardware covers it (`occlusion`). */
|
|
26
|
+
data class Regions(val division: List<Region>, val occlusion: List<Region>) {
|
|
27
|
+
val isEmpty: Boolean get() = division.isEmpty() && occlusion.isEmpty()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Which screen of its pair a screen is, how the pair lies, whether it lies over the other one and is hidden. */
|
|
31
|
+
data class Arrangement(val placement: String, val layout: String, val front: Boolean, val hidden: Boolean)
|
|
32
|
+
|
|
33
|
+
/** Where the changes JavaScript hears go: the events of the screen's JavaScript, or a test's record. */
|
|
34
|
+
interface Changes {
|
|
35
|
+
fun insetsChanged(screenId: String, insets: Insets)
|
|
36
|
+
|
|
37
|
+
fun regionsChanged(screenId: String, regions: Regions)
|
|
38
|
+
|
|
39
|
+
fun arrangementChanged(screenId: String, arrangement: Arrangement)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// One screen's record; null for a fact not known yet (not laid out, outside a pair).
|
|
43
|
+
private data class Record(
|
|
44
|
+
val insets: Insets? = null,
|
|
45
|
+
val padding: Insets? = null,
|
|
46
|
+
val regions: Regions? = null,
|
|
47
|
+
val arrangement: Arrangement? = null,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
private val NO_REGIONS = Regions(emptyList(), emptyList())
|
|
51
|
+
private val records = ConcurrentHashMap<String, Record>()
|
|
52
|
+
// Main thread only.
|
|
53
|
+
private val paddingListeners = HashMap<String, MutableSet<() -> Unit>>()
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Keeps the screen's [insets] for JavaScript (what still covers its content) and the [padding] of its safe area
|
|
57
|
+
* view. Calls the screen's padding listeners when the padding changed, then tells JavaScript when the insets did.
|
|
58
|
+
* Main thread only.
|
|
59
|
+
*/
|
|
60
|
+
fun setInsets(screenId: String, insets: Insets, padding: Insets, changes: Changes) {
|
|
61
|
+
val before = update(screenId) { it.copy(insets = insets, padding = padding) }
|
|
62
|
+
if (before?.padding != padding) paddingListeners[screenId]?.toList()?.forEach { it() }
|
|
63
|
+
if (before?.insets != insets) changes.insetsChanged(screenId, insets)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Keeps the screen's [regions], and tells JavaScript when they changed; none at first is what JavaScript reads
|
|
68
|
+
* before the first layout, so it isn't told. Main thread only.
|
|
69
|
+
*/
|
|
70
|
+
fun setRegions(screenId: String, regions: Regions, changes: Changes) {
|
|
71
|
+
val before = update(screenId) { it.copy(regions = regions) }?.regions
|
|
72
|
+
if (before == regions || (before == null && regions.isEmpty)) return
|
|
73
|
+
changes.regionsChanged(screenId, regions)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Keeps the screen's [arrangement], and tells JavaScript when it changed and [notify] holds. Main thread only. */
|
|
77
|
+
fun setArrangement(screenId: String, arrangement: Arrangement, notify: Boolean, changes: Changes) {
|
|
78
|
+
val before = update(screenId) { it.copy(arrangement = arrangement) }?.arrangement
|
|
79
|
+
if (before == arrangement || !notify) return
|
|
80
|
+
changes.arrangementChanged(screenId, arrangement)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** The padding of the screen's safe area view; none before the screen was laid out. Any thread. */
|
|
84
|
+
fun padding(screenId: String): Insets? = records[screenId]?.padding
|
|
85
|
+
|
|
86
|
+
/** The insets JavaScript gets; none before the screen was laid out. Any thread. */
|
|
87
|
+
fun insets(screenId: String): Insets? = records[screenId]?.insets
|
|
88
|
+
|
|
89
|
+
/** The screen's reserved regions; none before its first layout. Any thread. */
|
|
90
|
+
fun regions(screenId: String): Regions? = records[screenId]?.regions
|
|
91
|
+
|
|
92
|
+
/** The screen's arrangement; none outside a pair. Any thread. */
|
|
93
|
+
fun arrangement(screenId: String): Arrangement? = records[screenId]?.arrangement
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Calls `listener` when the padding of the screen changes; returns the function that stops it. Main thread only.
|
|
97
|
+
*/
|
|
98
|
+
fun listenToPadding(screenId: String, listener: () -> Unit): () -> Unit {
|
|
99
|
+
paddingListeners.getOrPut(screenId) { LinkedHashSet() }.add(listener)
|
|
100
|
+
return {
|
|
101
|
+
paddingListeners[screenId]?.let {
|
|
102
|
+
it.remove(listener)
|
|
103
|
+
if (it.isEmpty()) paddingListeners.remove(screenId)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Forgets everything kept for the screen. Its padding listeners stay: a live safe area view keeps listening while
|
|
110
|
+
* it keeps the id, and stops itself.
|
|
111
|
+
*/
|
|
112
|
+
fun remove(screenId: String) {
|
|
113
|
+
records.remove(screenId)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** `getScreenInsets`: `{ top, right, bottom, left }`, empty before the screen was laid out. Any thread. */
|
|
117
|
+
fun getScreenInsets(screenId: String): WritableMap = insets(screenId)?.let(::toMap) ?: Arguments.createMap()
|
|
118
|
+
|
|
119
|
+
/** `getScreenRegions`: `{ division, occlusion }`, empty lists before the first layout. Any thread. */
|
|
120
|
+
fun getScreenRegions(screenId: String): WritableMap = toMap(regions(screenId) ?: NO_REGIONS)
|
|
121
|
+
|
|
122
|
+
/** `getArrangementState`: `{ placement, layout, front, hidden }`, empty outside a pair. Any thread. */
|
|
123
|
+
fun getArrangementState(screenId: String): WritableMap =
|
|
124
|
+
arrangement(screenId)?.let(::toMap) ?: Arguments.createMap()
|
|
125
|
+
|
|
126
|
+
/** The changes as events through [emitter], the one of the JavaScript the screen was made for. */
|
|
127
|
+
fun changesOf(emitter: EventEmitter): Changes = object : Changes {
|
|
128
|
+
override fun insetsChanged(screenId: String, insets: Insets) =
|
|
129
|
+
emitter.emitScreenInsetsChanged(screenId, toMap(insets))
|
|
130
|
+
|
|
131
|
+
override fun regionsChanged(screenId: String, regions: Regions) =
|
|
132
|
+
emitter.emitScreenRegionsChanged(screenId, toMap(regions))
|
|
133
|
+
|
|
134
|
+
override fun arrangementChanged(screenId: String, arrangement: Arrangement) =
|
|
135
|
+
emitter.emitArrangementChanged(screenId, toMap(arrangement))
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Replaces the screen's record at once with [change] of it; returns the record before, null for a new screen.
|
|
139
|
+
private fun update(screenId: String, change: (Record) -> Record): Record? {
|
|
140
|
+
var before: Record? = null
|
|
141
|
+
records.compute(screenId) { _, old ->
|
|
142
|
+
before = old
|
|
143
|
+
change(old ?: Record())
|
|
144
|
+
}
|
|
145
|
+
return before
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private fun toMap(value: Insets): WritableMap = Arguments.createMap().apply {
|
|
149
|
+
putDouble(EventContract.ScreenInsetsChanged.TOP, value.top)
|
|
150
|
+
putDouble(EventContract.ScreenInsetsChanged.RIGHT, value.right)
|
|
151
|
+
putDouble(EventContract.ScreenInsetsChanged.BOTTOM, value.bottom)
|
|
152
|
+
putDouble(EventContract.ScreenInsetsChanged.LEFT, value.left)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private fun toMap(value: Regions): WritableMap = Arguments.createMap().apply {
|
|
156
|
+
putArray(EventContract.ScreenRegionsChanged.DIVISION, toArray(value.division))
|
|
157
|
+
putArray(EventContract.ScreenRegionsChanged.OCCLUSION, toArray(value.occlusion))
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private fun toArray(regions: List<Region>): WritableArray = Arguments.createArray().apply {
|
|
161
|
+
for (region in regions) {
|
|
162
|
+
pushMap(Arguments.createMap().apply {
|
|
163
|
+
putDouble(EventContract.ScreenRegionRect.X, region.x)
|
|
164
|
+
putDouble(EventContract.ScreenRegionRect.Y, region.y)
|
|
165
|
+
putDouble(EventContract.ScreenRegionRect.WIDTH, region.width)
|
|
166
|
+
putDouble(EventContract.ScreenRegionRect.HEIGHT, region.height)
|
|
167
|
+
})
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private fun toMap(value: Arrangement): WritableMap = Arguments.createMap().apply {
|
|
172
|
+
putString(EventContract.ArrangementChanged.PLACEMENT, value.placement)
|
|
173
|
+
putString(EventContract.ArrangementChanged.LAYOUT, value.layout)
|
|
174
|
+
putBoolean(EventContract.ArrangementChanged.FRONT, value.front)
|
|
175
|
+
putBoolean(EventContract.ArrangementChanged.HIDDEN, value.hidden)
|
|
176
|
+
}
|
|
177
|
+
}
|