@apexnative/navigation 1.0.0-alpha.0 → 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 +128 -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/cli/upgrade/changelog.js +2 -2
- 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 +4 -25
- package/src/ARCHITECTURE.md +40 -27
- package/src/adapters/NativeANNTurboModule.ts +12 -2
- package/src/api/app/AppRegistry.ts +16 -2
- package/src/api/app/createNavigation.ts +203 -69
- package/src/api/commands/commands.ts +48 -7
- package/src/api/commands/presentation.ts +4 -3
- package/src/api/events/navigationEvents.ts +10 -4
- package/src/api/hooks/useNavigation.ts +9 -4
- package/src/api/hooks/useSafeAreaInsets.ts +4 -3
- package/src/api/index.ts +1 -0
- package/src/api/linking/dispatchedLinks.ts +18 -0
- package/src/api/linking/linking.ts +22 -1
- package/src/api/navigation.ts +4 -1
- package/src/api/options/OptionsChain.ts +2 -2
- package/src/api/screens/defineScreen.ts +49 -5
- package/src/api/screens/nativeScreens.ts +40 -4
- package/src/api/screens/registerScreens.tsx +185 -42
- package/src/api/theme/theme.ts +5 -0
- package/src/engine/commands.ts +70 -13
- package/src/engine/layout.ts +27 -11
- package/src/engine/nativeScreens.ts +10 -1
- package/src/engine/options.ts +45 -19
- package/src/engine/optionsChange.ts +107 -0
- package/src/engine/places.ts +65 -7
- package/src/engine/props.ts +30 -1
- package/src/engine/refresh.ts +97 -0
- package/src/engine/rememberedOptions.ts +74 -1
- package/src/engine/screens.tsx +76 -21
- package/src/interfaces/ComponentEvents.ts +4 -4
- package/src/interfaces/Events.ts +29 -10
- package/src/interfaces/Options.ts +1 -0
- package/src/interfaces/contract/commands.json +101 -0
- package/src/interfaces/contract/errors.json +275 -0
- package/src/interfaces/options/animations.ts +81 -22
- package/src/interfaces/options/bottomTabs.ts +21 -7
- package/src/interfaces/options/buttons.ts +23 -15
- package/src/interfaces/options/modals.ts +34 -26
- package/src/interfaces/options/sideMenu.ts +24 -6
- package/src/interfaces/options/stack.ts +17 -3
- package/src/interfaces/options/system.ts +18 -11
- package/src/interfaces/options/toolbar.ts +2 -2
- package/src/interfaces/options/topBar.ts +68 -38
- package/android/src/main/java/dev/apexnative/navigation/react/ArrangementStates.kt +0 -41
- package/android/src/main/java/dev/apexnative/navigation/react/ScreenInsets.kt +0 -69
- package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationStateReporter.kt +0 -62
- package/android/src/main/java/dev/apexnative/navigation/react/events/StateHold.kt +0 -62
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowPlacer.kt +0 -223
- package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStub.kt +0 -31
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMatrixAnimator.kt +0 -138
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PlainViewAnimator.kt +0 -88
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PropertyAnimatorCreator.kt +0 -33
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ReactImageAnimator.kt +0 -66
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextChangeAnimator.kt +0 -179
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewChangeAnimator.kt +0 -139
- package/ios/Layouts/Screen/ANNScreenInsets.h +0 -30
- package/ios/Layouts/Screen/ANNScreenInsets.mm +0 -68
- package/ios/Layouts/Tabs/ANNTabsPreloadWindow.h +0 -27
- package/ios/Layouts/Tabs/ANNTabsPreloadWindow.mm +0 -55
package/cli/doctor/checks/app.js
CHANGED
|
@@ -11,8 +11,10 @@ const {
|
|
|
11
11
|
reactNativeVersion,
|
|
12
12
|
usesExpo,
|
|
13
13
|
} = require('../../app');
|
|
14
|
+
const { mainActivity } = require('../../links/native');
|
|
14
15
|
const { findProject } = require('../../project');
|
|
15
16
|
const { codeOf } = require('../../setup/source');
|
|
17
|
+
const { loadsReactNativeItself } = require('../../setup/steps/mainApplication');
|
|
16
18
|
const { planCodegen } = require('../../codegen');
|
|
17
19
|
const { readConfig } = require('../../config');
|
|
18
20
|
const { planProject } = require('../../setup');
|
|
@@ -27,6 +29,16 @@ const { splashChecks } = require('./splash');
|
|
|
27
29
|
const SETUP = { label: 'npx apex-navigation setup', run: /** @type {const} */ ('setup') };
|
|
28
30
|
const GENERATED = ['ApexNavigation.generated.swift', 'ApexNavigationGenerated.kt'];
|
|
29
31
|
const CODEGEN = { label: 'npx apex-navigation codegen', run: /** @type {const} */ ('codegen') };
|
|
32
|
+
// The changes the main activity must handle itself; the template's value has them all.
|
|
33
|
+
const CONFIG_CHANGES = [
|
|
34
|
+
'orientation',
|
|
35
|
+
'screenSize',
|
|
36
|
+
'smallestScreenSize',
|
|
37
|
+
'screenLayout',
|
|
38
|
+
'uiMode',
|
|
39
|
+
];
|
|
40
|
+
const TEMPLATE_CONFIG_CHANGES =
|
|
41
|
+
'keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode';
|
|
30
42
|
|
|
31
43
|
/**
|
|
32
44
|
* React Native, the navigation, and the files setup sets up.
|
|
@@ -88,11 +100,12 @@ function appChecks({ root, run }) {
|
|
|
88
100
|
const project = findProject(root, run);
|
|
89
101
|
const plans = planProject(project);
|
|
90
102
|
const app = plans.find(({ file }) => file !== undefined && file === project.app);
|
|
103
|
+
const metro = plans.find(({ file }) => file !== undefined && file === project.metroConfig);
|
|
91
104
|
const manifest = plans.find(({ file }) => file !== undefined && file === project.manifest);
|
|
92
105
|
const native = plans.filter((plan) => plan.platform !== 'js' && plan !== manifest);
|
|
93
106
|
const types = plans.filter(({ name }) => name === ENV_FILE || name === 'tsconfig.json');
|
|
94
107
|
const entry = plans.filter(
|
|
95
|
-
(plan) => plan.platform === 'js' && plan !== app && !types.includes(plan)
|
|
108
|
+
(plan) => plan.platform === 'js' && plan !== app && plan !== metro && !types.includes(plan)
|
|
96
109
|
);
|
|
97
110
|
checks.push(filesCheck('Native files', native), filesCheck('Entry point', entry));
|
|
98
111
|
const typed = typesCheck(root, types);
|
|
@@ -108,6 +121,20 @@ function appChecks({ root, run }) {
|
|
|
108
121
|
});
|
|
109
122
|
}
|
|
110
123
|
|
|
124
|
+
// Without the navigation's Metro setup an edit that isn't a boundary of Fast Refresh reloads the app.
|
|
125
|
+
if (metro && metro.status !== 'done') {
|
|
126
|
+
checks.push({
|
|
127
|
+
group: 'app',
|
|
128
|
+
title: 'Fast Refresh',
|
|
129
|
+
status: 'warn',
|
|
130
|
+
detail: `${metro.name} doesn't use withApexNavigation: some edits reload the app`,
|
|
131
|
+
fix:
|
|
132
|
+
metro.status === 'manual'
|
|
133
|
+
? { label: 'Wrap the config metro.config.js exports in withApexNavigation' }
|
|
134
|
+
: SETUP,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
111
138
|
// Predictive back is optional: without it the navigation works, and Android plays no back animation of its own.
|
|
112
139
|
if (manifest && manifest.status !== 'done') {
|
|
113
140
|
checks.push({
|
|
@@ -122,28 +149,64 @@ function appChecks({ root, run }) {
|
|
|
122
149
|
});
|
|
123
150
|
}
|
|
124
151
|
|
|
152
|
+
const configChanges = configChangesCheck(project.manifest);
|
|
153
|
+
if (configChanges) checks.push(configChanges);
|
|
154
|
+
|
|
125
155
|
checks.push(...splashChecks(root, project), ...iconChecks(root, project));
|
|
126
156
|
|
|
127
|
-
//
|
|
157
|
+
// NavigationApplication leaves the load of React Native to the template's call: without it the app closes on start,
|
|
158
|
+
// and so it does with a second load of the app's own next to it.
|
|
128
159
|
const application = project.mainApplication && fs.readFileSync(project.mainApplication, 'utf8');
|
|
129
|
-
if (
|
|
130
|
-
application
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
160
|
+
if (application && /:\s*NavigationApplication\(/.test(application)) {
|
|
161
|
+
const loads = /\bloadReactNative\s*\(/.test(codeOf(application));
|
|
162
|
+
if (!loads) {
|
|
163
|
+
checks.push({
|
|
164
|
+
group: 'app',
|
|
165
|
+
title: 'React Native not loaded',
|
|
166
|
+
status: 'error',
|
|
167
|
+
detail: "MainApplication.kt doesn't call loadReactNative(this) in onCreate",
|
|
168
|
+
fix: SETUP,
|
|
169
|
+
});
|
|
170
|
+
} else if (loadsReactNativeItself(application)) {
|
|
171
|
+
checks.push({
|
|
172
|
+
group: 'app',
|
|
173
|
+
title: 'React Native loads twice',
|
|
174
|
+
status: 'error',
|
|
175
|
+
detail:
|
|
176
|
+
'MainApplication.kt loads React Native itself (SoLoader.init or the New Architecture entry point) next to loadReactNative(this)',
|
|
177
|
+
fix: SETUP,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
141
180
|
}
|
|
142
181
|
const generated = generatedCheck(root, run);
|
|
143
182
|
if (generated) checks.push(generated);
|
|
144
183
|
return checks;
|
|
145
184
|
}
|
|
146
185
|
|
|
186
|
+
/**
|
|
187
|
+
* Whether the main activity handles the changes of its window itself, as the React Native template has it. Without
|
|
188
|
+
* one of them Android recreates the activity on a rotation, a resize, a fold or a light/dark switch: every screen goes
|
|
189
|
+
* with it and the navigation starts again from its root. Nothing without a manifest or a main activity.
|
|
190
|
+
* @param {string | undefined} manifest
|
|
191
|
+
* @returns {Check | undefined}
|
|
192
|
+
*/
|
|
193
|
+
function configChangesCheck(manifest) {
|
|
194
|
+
if (!manifest || !fs.existsSync(manifest)) return undefined;
|
|
195
|
+
const activity = mainActivity(fs.readFileSync(manifest, 'utf8'));
|
|
196
|
+
if (!activity) return undefined;
|
|
197
|
+
const value = /android:configChanges\s*=\s*(?:"([^"]*)"|'([^']*)')/.exec(activity.text);
|
|
198
|
+
const declared = (value?.[1] ?? value?.[2] ?? '').split('|').map((change) => change.trim());
|
|
199
|
+
const missing = CONFIG_CHANGES.filter((change) => !declared.includes(change));
|
|
200
|
+
if (missing.length === 0) return undefined;
|
|
201
|
+
return {
|
|
202
|
+
group: 'app',
|
|
203
|
+
title: 'Config changes',
|
|
204
|
+
status: 'warn',
|
|
205
|
+
detail: `the main activity doesn't handle ${missing.join(', ')}: Android recreates it, and every screen with it`,
|
|
206
|
+
fix: { label: `Set android:configChanges="${TEMPLATE_CONFIG_CHANGES}" on the main activity` },
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
147
210
|
/**
|
|
148
211
|
* One line for a few files: set up, or which need setup or a change by hand.
|
|
149
212
|
* @param {string} title
|
|
@@ -17,34 +17,16 @@ const CIRCLE = 192;
|
|
|
17
17
|
const LOGO_HEIGHT = /<dimen name="apex_navigation_splash_logo_height">([\d.]+)dp<\/dimen>/;
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* The native splash: made from its settings in package.json on both platforms, its logo whole on Android 12
|
|
21
|
-
* settings
|
|
20
|
+
* The native splash: made from its settings in package.json on both platforms, its logo whole on Android 12+. Without
|
|
21
|
+
* settings there is nothing to check: the navigation keeps a copy of a storyboard and of `UILaunchScreen` alike.
|
|
22
22
|
* @param {string} root
|
|
23
23
|
* @param {Project} project
|
|
24
24
|
* @returns {Check[]}
|
|
25
25
|
*/
|
|
26
26
|
function splashChecks(root, project) {
|
|
27
|
-
const plist = project.infoPlist && fs.readFileSync(project.infoPlist, 'utf8');
|
|
28
27
|
const saved = readConfig(root).splash;
|
|
29
|
-
if (!saved)
|
|
30
|
-
|
|
31
|
-
if (
|
|
32
|
-
plist?.includes('<key>UILaunchScreen</key>') &&
|
|
33
|
-
!plist.includes('<key>UILaunchStoryboardName</key>')
|
|
34
|
-
) {
|
|
35
|
-
return [
|
|
36
|
-
{
|
|
37
|
-
group: 'app',
|
|
38
|
-
title: 'Launch screen',
|
|
39
|
-
status: 'warn',
|
|
40
|
-
detail:
|
|
41
|
-
'UILaunchScreen in Info.plist: an empty window shows between it and the first screen',
|
|
42
|
-
fix: SPLASH,
|
|
43
|
-
},
|
|
44
|
-
];
|
|
45
|
-
}
|
|
46
|
-
return [];
|
|
47
|
-
}
|
|
28
|
+
if (!saved) return [];
|
|
29
|
+
const plist = project.infoPlist && fs.readFileSync(project.infoPlist, 'utf8');
|
|
48
30
|
const resolved = resolveSettings(root, {}, saved);
|
|
49
31
|
if ('errors' in resolved) {
|
|
50
32
|
return [
|
package/cli/migrate/native.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
const fs = require('node:fs');
|
|
5
5
|
const path = require('node:path');
|
|
6
|
+
const { withReactNativeLoaded } = require('../setup/steps/mainApplication');
|
|
6
7
|
|
|
7
8
|
/** @typedef {import('../changes').FileChange} FileChange */
|
|
8
9
|
/** @typedef {import('./report').ReportItem} ReportItem */
|
|
@@ -158,6 +159,23 @@ function planNative(project) {
|
|
|
158
159
|
const before = fs.readFileSync(file, 'utf8');
|
|
159
160
|
let next = before;
|
|
160
161
|
for (const [pattern, replacement] of rewrite.rules) next = next.replace(pattern, replacement);
|
|
162
|
+
// react-native-navigation loaded React Native itself; the navigation's application leaves it to the template's
|
|
163
|
+
// loadReactNative(this), which such an app doesn't have.
|
|
164
|
+
if (file === project.mainApplication && /:\s*NavigationApplication\(/.test(next)) {
|
|
165
|
+
const loaded = withReactNativeLoaded(next);
|
|
166
|
+
if (loaded !== undefined) next = loaded;
|
|
167
|
+
else {
|
|
168
|
+
report.push({
|
|
169
|
+
file: path.relative(root, file),
|
|
170
|
+
line: 1,
|
|
171
|
+
step: 'native',
|
|
172
|
+
before: 'onCreate',
|
|
173
|
+
after: 'super.onCreate() then loadReactNative(this), and no load of its own',
|
|
174
|
+
what: 'React Native loads through loadReactNative(this) in onCreate: add it by hand',
|
|
175
|
+
docs: `${DOCS}#native`,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
161
179
|
if (next !== before) {
|
|
162
180
|
changes.push({
|
|
163
181
|
name: path.basename(file),
|
package/cli/project.js
CHANGED
|
@@ -8,8 +8,9 @@ const { exec } = require('./exec');
|
|
|
8
8
|
/**
|
|
9
9
|
* The files of the app the CLI sets up, checks and adds to, where the app has them; `undefined` for one it couldn't
|
|
10
10
|
* find. `styles` is the file of the app's Android theme, `styles.xml` or `themes.xml`; `manifest` its
|
|
11
|
-
* `AndroidManifest.xml`. `
|
|
12
|
-
*
|
|
11
|
+
* `AndroidManifest.xml`. `sceneDelegate` is the `SceneDelegate.swift` next to `AppDelegate.swift`, which apps made
|
|
12
|
+
* from React Native 0.88's template have. `xcodeProject` is the app's `project.pbxproj`; `androidPackage` the package
|
|
13
|
+
* of its Kotlin code (the `namespace` of `android/app/build.gradle`), and `androidSources` the folder it is in.
|
|
13
14
|
* @typedef {{
|
|
14
15
|
* root: string;
|
|
15
16
|
* mainApplication?: string;
|
|
@@ -17,9 +18,11 @@ const { exec } = require('./exec');
|
|
|
17
18
|
* styles?: string;
|
|
18
19
|
* manifest?: string;
|
|
19
20
|
* appDelegate?: string;
|
|
21
|
+
* sceneDelegate?: string;
|
|
20
22
|
* infoPlist?: string;
|
|
21
23
|
* entry?: string;
|
|
22
24
|
* app?: string;
|
|
25
|
+
* metroConfig?: string;
|
|
23
26
|
* typescript: boolean;
|
|
24
27
|
* xcodeProject?: string;
|
|
25
28
|
* androidPackage?: string;
|
|
@@ -64,6 +67,8 @@ function findProject(root, run = exec) {
|
|
|
64
67
|
existing(path.join(androidMain, 'res', 'values', 'themes.xml')),
|
|
65
68
|
manifest: existing(path.join(androidMain, 'AndroidManifest.xml')),
|
|
66
69
|
appDelegate,
|
|
70
|
+
sceneDelegate:
|
|
71
|
+
appDelegate && existing(path.join(path.dirname(appDelegate), 'SceneDelegate.swift')),
|
|
67
72
|
infoPlist: appDelegate && existing(path.join(path.dirname(appDelegate), 'Info.plist')),
|
|
68
73
|
entry: ['index.js', 'index.ts', 'index.tsx']
|
|
69
74
|
.map((name) => path.join(root, name))
|
|
@@ -71,6 +76,9 @@ function findProject(root, run = exec) {
|
|
|
71
76
|
app: ['App.tsx', 'App.ts', 'App.jsx', 'App.js']
|
|
72
77
|
.map((name) => path.join(root, name))
|
|
73
78
|
.find((file) => fs.existsSync(file)),
|
|
79
|
+
metroConfig: ['metro.config.js', 'metro.config.cjs']
|
|
80
|
+
.map((name) => path.join(root, name))
|
|
81
|
+
.find((file) => fs.existsSync(file)),
|
|
74
82
|
typescript: ['App.tsx', 'App.ts', 'tsconfig.json'].some((name) =>
|
|
75
83
|
fs.existsSync(path.join(root, name))
|
|
76
84
|
),
|
package/cli/setup/index.js
CHANGED
|
@@ -16,6 +16,8 @@ const { planEntry, navigationFile, HOW_TO: ENTRY_HOW_TO } = require('./steps/ent
|
|
|
16
16
|
const { planEnv, targetOf } = require('./steps/env');
|
|
17
17
|
const { planInfoPlist } = require('./steps/infoPlist');
|
|
18
18
|
const { planMainActivity } = require('./steps/mainActivity');
|
|
19
|
+
const { planMetro } = require('./steps/metro');
|
|
20
|
+
const { planSceneDelegate } = require('./steps/sceneDelegate');
|
|
19
21
|
const { planMainApplication } = require('./steps/mainApplication');
|
|
20
22
|
const { planManifest } = require('./steps/manifest');
|
|
21
23
|
const { planStyles } = require('./steps/styles');
|
|
@@ -83,6 +85,18 @@ function planProject(project) {
|
|
|
83
85
|
planAppDelegate,
|
|
84
86
|
notFound('AppDelegate.swift')
|
|
85
87
|
),
|
|
88
|
+
// React Native 0.88's template starts React Native in its scene delegate; the earlier templates have none.
|
|
89
|
+
...(project.sceneDelegate
|
|
90
|
+
? [
|
|
91
|
+
planFile(
|
|
92
|
+
'SceneDelegate.swift',
|
|
93
|
+
'ios',
|
|
94
|
+
project.sceneDelegate,
|
|
95
|
+
planSceneDelegate,
|
|
96
|
+
notFound('SceneDelegate.swift')
|
|
97
|
+
),
|
|
98
|
+
]
|
|
99
|
+
: []),
|
|
86
100
|
planFile('Info.plist', 'ios', project.infoPlist, planInfoPlist, notFound('Info.plist')),
|
|
87
101
|
planFile('index.js', 'js', project.entry, planEntry, ENTRY_HOW_TO),
|
|
88
102
|
];
|
|
@@ -121,6 +135,10 @@ function planProject(project) {
|
|
|
121
135
|
plans.push(...planEnv(project.root, navigation, ts));
|
|
122
136
|
// The template's App renders React Native's status bar; one moved elsewhere or written anew has nothing to change.
|
|
123
137
|
if (project.app) plans.push(planFile('App.tsx', 'js', project.app, planApp, APP_HOW_TO));
|
|
138
|
+
// Fast Refresh for every edit; an app without a Metro config of its own has nothing to change.
|
|
139
|
+
if (project.metroConfig) {
|
|
140
|
+
plans.push(planFile('metro.config.js', 'js', project.metroConfig, planMetro, ''));
|
|
141
|
+
}
|
|
124
142
|
return plans;
|
|
125
143
|
}
|
|
126
144
|
|
package/cli/setup/source.js
CHANGED
|
@@ -35,7 +35,8 @@ function removeUnusedImports(text, names) {
|
|
|
35
35
|
for (const name of names) {
|
|
36
36
|
const line = new RegExp(`^import\\s+${escape(name)}[ \\t]*\\r?\\n`, 'm');
|
|
37
37
|
const simple = name.slice(name.lastIndexOf('.') + 1);
|
|
38
|
-
|
|
38
|
+
// A name in a comment is no use of the import.
|
|
39
|
+
const code = codeOf(result).replace(/^import\s.*$/gm, '');
|
|
39
40
|
if (line.test(result) && !new RegExp(`\\b${escape(simple)}\\b`).test(code))
|
|
40
41
|
result = result.replace(line, '');
|
|
41
42
|
}
|
|
@@ -19,7 +19,10 @@ its delegate (the bundle URL) before calling super.
|
|
|
19
19
|
self.reactNativeDelegate = ReactNativeDelegate()
|
|
20
20
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
|
21
21
|
}
|
|
22
|
-
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
ReactNativeDelegate is the app's RCTDefaultReactNativeFactoryDelegate, which gives the bundle URL (bundleURL()); in
|
|
25
|
+
React Native 0.88's template that method is in SceneDelegate.`;
|
|
23
26
|
|
|
24
27
|
// Lines of the template's launch: ANNAppDelegate does all of it.
|
|
25
28
|
const TEMPLATE_LINES = [
|
|
@@ -42,6 +45,20 @@ const LAUNCH_OVERRIDE =
|
|
|
42
45
|
const DELEGATE = /^([ \t]*)let\s+delegate\s*=\s*ReactNativeDelegate\(\)[ \t]*$/m;
|
|
43
46
|
const RETURN_TRUE = /^([ \t]*)return\s+true[ \t]*$/m;
|
|
44
47
|
|
|
48
|
+
// React Native 0.88's template starts React Native in its scene delegate: the app delegate only returns true. The
|
|
49
|
+
// bundle URL moves into a delegate of React Native's factory, as the earlier templates had it.
|
|
50
|
+
const REACT_NATIVE_DELEGATE = `class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate {
|
|
51
|
+
override func bundleURL() -> URL? {
|
|
52
|
+
#if DEBUG
|
|
53
|
+
RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
|
|
54
|
+
#else
|
|
55
|
+
Bundle.main.url(forResource: "main", withExtension: "jsbundle")
|
|
56
|
+
#endif
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
`;
|
|
60
|
+
const RETURN_TRUE_OR_TRUE = /^([ \t]*)(?:return\s+)?true[ \t]*$/m;
|
|
61
|
+
|
|
45
62
|
/**
|
|
46
63
|
* AppDelegate.swift: the app delegate becomes an ANNAppDelegate.
|
|
47
64
|
* @param {string} text
|
|
@@ -55,13 +72,30 @@ function planAppDelegate(text) {
|
|
|
55
72
|
note: 'changed by hand, see below',
|
|
56
73
|
howTo: HOW_TO,
|
|
57
74
|
});
|
|
58
|
-
if (!HEADER.test(text) || !LAUNCH.test(text)
|
|
75
|
+
if (!HEADER.test(text) || !LAUNCH.test(text)) return manual;
|
|
76
|
+
let next = DELEGATE.test(text) ? fromFactoryLaunch(text) : fromSceneLaunch(text);
|
|
77
|
+
if (next === undefined) return manual;
|
|
59
78
|
|
|
79
|
+
// The dependency provider is ANNAppDelegate's now.
|
|
80
|
+
if (!/\bRCTAppDependencyProvider\b/.test(next)) {
|
|
81
|
+
next = next.replace(/^import\s+ReactAppDependencyProvider[ \t]*\n/m, '');
|
|
82
|
+
}
|
|
83
|
+
next = addImport(next, 'import ApexNavigation', { sorted: false });
|
|
84
|
+
return { status: 'change', next, note: 'ANNAppDelegate' };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* The app delegate of the templates before React Native 0.88, which makes React Native's factory and window in its
|
|
89
|
+
* launch; undefined when the launch has code of the app's own that uses them.
|
|
90
|
+
* @param {string} text
|
|
91
|
+
* @returns {string | undefined}
|
|
92
|
+
*/
|
|
93
|
+
function fromFactoryLaunch(text) {
|
|
60
94
|
let next = text
|
|
61
95
|
.replace(HEADER, 'class $1: ANNAppDelegate {')
|
|
62
96
|
.replace(LAUNCH, '$1override func$2');
|
|
63
97
|
for (const line of TEMPLATE_LINES) {
|
|
64
|
-
if (!line.test(next)) return
|
|
98
|
+
if (!line.test(next)) return undefined;
|
|
65
99
|
next = next.replace(line, '');
|
|
66
100
|
}
|
|
67
101
|
next = next.replace(DELEGATE, '$1self.reactNativeDelegate = ReactNativeDelegate()');
|
|
@@ -69,10 +103,10 @@ function planAppDelegate(text) {
|
|
|
69
103
|
// The launch now ends in super's, which starts React Native.
|
|
70
104
|
const launchAt = next.search(LAUNCH_OVERRIDE);
|
|
71
105
|
const returnAt = next.slice(launchAt).search(RETURN_TRUE);
|
|
72
|
-
if (returnAt < 0) return
|
|
106
|
+
if (returnAt < 0) return undefined;
|
|
73
107
|
const body = next.slice(launchAt, launchAt + returnAt).replace(/self\.reactNativeDelegate/g, '');
|
|
74
108
|
// Code of the app's own that used the template's factory, delegate or window: it has to move by hand.
|
|
75
|
-
if (/\b(factory|delegate|window)\b/.test(body)) return
|
|
109
|
+
if (/\b(factory|delegate|window)\b/.test(body)) return undefined;
|
|
76
110
|
const rest = next
|
|
77
111
|
.slice(launchAt + returnAt)
|
|
78
112
|
.replace(
|
|
@@ -82,17 +116,38 @@ function planAppDelegate(text) {
|
|
|
82
116
|
next = next.slice(0, launchAt + returnAt) + rest;
|
|
83
117
|
|
|
84
118
|
// The blank lines the template's launch leaves behind.
|
|
85
|
-
|
|
119
|
+
return next
|
|
86
120
|
.replace(/(class\s+\w+:\s*ANNAppDelegate\s*\{\n)(?:[ \t]*\n)+/, '$1')
|
|
87
121
|
.replace(/(self\.reactNativeDelegate = ReactNativeDelegate\(\)\n)(?:[ \t]*\n)+/, '$1')
|
|
88
122
|
.replace(/\n(?:[ \t]*\n)+([ \t]*return super\.application\()/, '\n$1');
|
|
123
|
+
}
|
|
89
124
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
125
|
+
/**
|
|
126
|
+
* The app delegate of React Native 0.88's template, whose launch only returns true; undefined when the app delegate
|
|
127
|
+
* makes React Native or a window of its own.
|
|
128
|
+
* @param {string} text
|
|
129
|
+
* @returns {string | undefined}
|
|
130
|
+
*/
|
|
131
|
+
function fromSceneLaunch(text) {
|
|
132
|
+
if (/\b(RCTReactNativeFactory|ReactNativeDelegate|window)\b/.test(text)) return undefined;
|
|
133
|
+
let next = text
|
|
134
|
+
.replace(HEADER, 'class $1: ANNAppDelegate {')
|
|
135
|
+
.replace(LAUNCH, '$1override func$2');
|
|
136
|
+
const launchAt = next.search(LAUNCH_OVERRIDE);
|
|
137
|
+
const returnAt = next.slice(launchAt).search(RETURN_TRUE_OR_TRUE);
|
|
138
|
+
if (returnAt < 0) return undefined;
|
|
139
|
+
const rest = next
|
|
140
|
+
.slice(launchAt + returnAt)
|
|
141
|
+
.replace(
|
|
142
|
+
RETURN_TRUE_OR_TRUE,
|
|
143
|
+
'$1self.reactNativeDelegate = ReactNativeDelegate()\n' +
|
|
144
|
+
'$1return super.application(application, didFinishLaunchingWithOptions: launchOptions)'
|
|
145
|
+
);
|
|
146
|
+
next = `${next.slice(0, launchAt + returnAt)}${rest.trimEnd()}\n\n${REACT_NATIVE_DELEGATE}`;
|
|
147
|
+
for (const module of ['React', 'React_RCTAppDelegate']) {
|
|
148
|
+
next = addImport(next, `import ${module}`, { sorted: false });
|
|
93
149
|
}
|
|
94
|
-
|
|
95
|
-
return { status: 'change', next, note: 'ANNAppDelegate' };
|
|
150
|
+
return next;
|
|
96
151
|
}
|
|
97
152
|
|
|
98
153
|
module.exports = { planAppDelegate };
|
|
@@ -5,24 +5,51 @@ const { addImport, codeOf, removeUnusedImports } = require('../source');
|
|
|
5
5
|
|
|
6
6
|
/** @typedef {import('./types').StepResult} StepResult */
|
|
7
7
|
|
|
8
|
-
const HOW_TO = `Extend NavigationApplication
|
|
9
|
-
|
|
8
|
+
const HOW_TO = `Extend NavigationApplication and keep the template's loadReactNative(this) in onCreate: it loads
|
|
9
|
+
React Native as the app's Gradle files say, and the navigation makes its React host after it.
|
|
10
10
|
|
|
11
|
+
import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative
|
|
11
12
|
import dev.apexnative.navigation.NavigationApplication
|
|
12
13
|
|
|
13
14
|
class MainApplication : NavigationApplication() {
|
|
14
15
|
override val reactHost: ReactHost by lazy { ... } // as it is
|
|
16
|
+
|
|
17
|
+
override fun onCreate() {
|
|
18
|
+
super.onCreate()
|
|
19
|
+
loadReactNative(this)
|
|
20
|
+
}
|
|
15
21
|
}`;
|
|
16
22
|
|
|
23
|
+
const LOAD_IMPORT = 'import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative';
|
|
24
|
+
|
|
17
25
|
// Imports of the template that the change leaves unused.
|
|
18
|
-
const TEMPLATE_IMPORTS = [
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
26
|
+
const TEMPLATE_IMPORTS = ['android.app.Application', 'com.facebook.react.ReactApplication'];
|
|
27
|
+
|
|
28
|
+
// A load of React Native of the app's own, next to loadReactNative(this) a second one that crashes the app at start:
|
|
29
|
+
// the New Architecture's entry point (react-native-navigation's apps call it in onCreate) and SoLoader.
|
|
30
|
+
// A bare `load()` is the entry point's only where the file imports it. A form these don't take out (`load` with
|
|
31
|
+
// arguments, an `if` without braces) is left to the app's author.
|
|
32
|
+
const OWN_LOAD = [
|
|
33
|
+
/^[ \t]*if\s*\(\s*BuildConfig\.IS_NEW_ARCHITECTURE_ENABLED\s*\)\s*\{(?:\s*\/\/[^\n]*)*\s*DefaultNewArchitectureEntryPoint\.load\(\)\s*\}[ \t]*\r?\n/gm,
|
|
34
|
+
/^[ \t]*DefaultNewArchitectureEntryPoint\.load\(\)[ \t]*\r?\n/gm,
|
|
35
|
+
/^[ \t]*SoLoader\.init\([^\n]*\)[ \t]*\r?\n/gm,
|
|
36
|
+
];
|
|
37
|
+
const BARE_LOAD = [
|
|
38
|
+
/^[ \t]*if\s*\(\s*BuildConfig\.IS_NEW_ARCHITECTURE_ENABLED\s*\)\s*\{(?:\s*\/\/[^\n]*)*\s*load\(\)\s*\}[ \t]*\r?\n/gm,
|
|
39
|
+
/^[ \t]*load\(\)[ \t]*\r?\n/gm,
|
|
40
|
+
];
|
|
41
|
+
const BARE_LOAD_IMPORT =
|
|
42
|
+
/^import\s+com\.facebook\.react\.defaults\.DefaultNewArchitectureEntryPoint\.load\b/m;
|
|
43
|
+
const OWN_LOAD_IMPORTS = [
|
|
44
|
+
'com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load',
|
|
45
|
+
'com.facebook.react.defaults.DefaultNewArchitectureEntryPoint',
|
|
46
|
+
'com.facebook.soloader.SoLoader',
|
|
47
|
+
'com.facebook.react.soloader.OpenSourceMergedSoMapping',
|
|
22
48
|
];
|
|
23
49
|
|
|
24
50
|
/**
|
|
25
|
-
* MainApplication.kt: the application becomes a NavigationApplication
|
|
51
|
+
* MainApplication.kt: the application becomes a NavigationApplication, and loads React Native in its onCreate as the
|
|
52
|
+
* template does.
|
|
26
53
|
* @param {string} text
|
|
27
54
|
* @returns {StepResult}
|
|
28
55
|
*/
|
|
@@ -32,21 +59,20 @@ function planMainApplication(text) {
|
|
|
32
59
|
note: 'changed by hand, see below',
|
|
33
60
|
howTo: HOW_TO,
|
|
34
61
|
});
|
|
35
|
-
if (/:\s*NavigationApplication\(
|
|
36
|
-
|
|
62
|
+
if (/:\s*NavigationApplication\(/.test(text)) {
|
|
63
|
+
if (loadsReactNative(text) && !loadsReactNativeItself(text)) {
|
|
64
|
+
return { status: 'done', note: 'already set up' };
|
|
65
|
+
}
|
|
66
|
+
const next = withReactNativeLoaded(text);
|
|
67
|
+
return next === undefined
|
|
37
68
|
? manual
|
|
38
|
-
: { status: '
|
|
69
|
+
: { status: 'change', next, note: 'loadReactNative(this) in onCreate' };
|
|
39
70
|
}
|
|
40
71
|
const header = /class\s+(\w+)\s*:\s*Application\(\)\s*,\s*ReactApplication\b/;
|
|
41
72
|
if (!header.test(text)) return manual;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
next
|
|
45
|
-
/\n\n?[ \t]*override\s+fun\s+onCreate\(\)\s*\{\s*super\.onCreate\(\)\s*loadReactNative\(this\)\s*\}/,
|
|
46
|
-
''
|
|
47
|
-
);
|
|
48
|
-
next = next.replace(/^[ \t]*loadReactNative\(this\)[ \t]*\r?\n/m, '');
|
|
49
|
-
if (/\bloadReactNative\s*\(/.test(codeOf(next))) return manual;
|
|
73
|
+
// The template's onCreate stays: its loadReactNative(this) loads React Native for the navigation too.
|
|
74
|
+
let next = withReactNativeLoaded(text.replace(header, 'class $1 : NavigationApplication()'));
|
|
75
|
+
if (next === undefined) return manual;
|
|
50
76
|
// Added first: with the template's imports gone the file would have none to sort it among.
|
|
51
77
|
next = addImport(next, 'import dev.apexnative.navigation.NavigationApplication', {
|
|
52
78
|
sorted: true,
|
|
@@ -55,4 +81,93 @@ function planMainApplication(text) {
|
|
|
55
81
|
return { status: 'change', next, note: 'NavigationApplication' };
|
|
56
82
|
}
|
|
57
83
|
|
|
58
|
-
|
|
84
|
+
/**
|
|
85
|
+
* Whether the code of the file, not a comment, calls loadReactNative.
|
|
86
|
+
* @param {string} text
|
|
87
|
+
*/
|
|
88
|
+
function loadsReactNative(text) {
|
|
89
|
+
return /\bloadReactNative\s*\(/.test(codeOf(text));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Whether the code of the file loads React Native on its own as well: the New Architecture's entry point or SoLoader.
|
|
94
|
+
* @param {string} text
|
|
95
|
+
*/
|
|
96
|
+
function loadsReactNativeItself(text) {
|
|
97
|
+
const code = codeOf(text);
|
|
98
|
+
return (
|
|
99
|
+
/\bSoLoader\.init\s*\(/.test(code) ||
|
|
100
|
+
/\bDefaultNewArchitectureEntryPoint\.load\s*\(/.test(code) ||
|
|
101
|
+
(BARE_LOAD_IMPORT.test(text) && /(?<![\w.])load\s*\(/.test(code))
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* The application with `loadReactNative(this)` in its onCreate, after `super.onCreate()`: as it is when it has the
|
|
107
|
+
* call, with an onCreate of the template's when it has none. Undefined for an onCreate that doesn't call
|
|
108
|
+
* `super.onCreate()`, whose order only its author knows.
|
|
109
|
+
* @param {string} text
|
|
110
|
+
* @returns {string | undefined}
|
|
111
|
+
*/
|
|
112
|
+
function withReactNativeLoaded(text) {
|
|
113
|
+
let without = text;
|
|
114
|
+
const patterns = BARE_LOAD_IMPORT.test(text) ? [...OWN_LOAD, ...BARE_LOAD] : OWN_LOAD;
|
|
115
|
+
for (const pattern of patterns) without = without.replace(pattern, '');
|
|
116
|
+
without = removeUnusedImports(without, OWN_LOAD_IMPORTS);
|
|
117
|
+
if (loadsReactNativeItself(without)) return undefined;
|
|
118
|
+
if (loadsReactNative(without)) return without;
|
|
119
|
+
return withLoadCall(without);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @param {string} text an application without a load of React Native
|
|
124
|
+
* @returns {string | undefined}
|
|
125
|
+
*/
|
|
126
|
+
function withLoadCall(text) {
|
|
127
|
+
let next;
|
|
128
|
+
const superCall = /^([ \t]*)super\.onCreate\(\)[ \t]*\r?\n/m;
|
|
129
|
+
if (/\boverride\s+fun\s+onCreate\s*\(/.test(text)) {
|
|
130
|
+
if (!superCall.test(text)) return undefined;
|
|
131
|
+
next = text.replace(superCall, (line, indent) => `${line}${indent}loadReactNative(this)\n`);
|
|
132
|
+
} else {
|
|
133
|
+
const close = classEnd(text);
|
|
134
|
+
if (close === undefined) return undefined;
|
|
135
|
+
const indent = /^([ \t]+)override\b/m.exec(text)?.[1] ?? ' ';
|
|
136
|
+
const body = text.slice(0, close).replace(/\s*$/, '');
|
|
137
|
+
const onCreate = [
|
|
138
|
+
'',
|
|
139
|
+
`${indent}override fun onCreate() {`,
|
|
140
|
+
`${indent}${indent}super.onCreate()`,
|
|
141
|
+
`${indent}${indent}loadReactNative(this)`,
|
|
142
|
+
`${indent}}`,
|
|
143
|
+
].join('\n');
|
|
144
|
+
next = `${body}\n${onCreate}\n${text.slice(close)}`;
|
|
145
|
+
}
|
|
146
|
+
return addImport(next, LOAD_IMPORT, { sorted: true });
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* The index of the closing brace of the file's application class: its braces counted from the class's own, past any
|
|
151
|
+
* declaration or comment after it. Undefined when the braces don't close.
|
|
152
|
+
* @param {string} text
|
|
153
|
+
* @returns {number | undefined}
|
|
154
|
+
*/
|
|
155
|
+
function classEnd(text) {
|
|
156
|
+
// The comments and the string and character literals blanked out, so that an index in it is one in the text and a
|
|
157
|
+
// brace in a literal doesn't count.
|
|
158
|
+
const blank = (/** @type {string} */ part) => part.replace(/[^\n]/g, ' ');
|
|
159
|
+
const code = text
|
|
160
|
+
.replace(/\/\*[\s\S]*?\*\//g, blank)
|
|
161
|
+
.replace(/\/\/.*$/gm, blank)
|
|
162
|
+
.replace(/"(?:[^"\\\n]|\\.)*"|'(?:[^'\\\n]|\\.)*'/g, blank);
|
|
163
|
+
const header = /\bclass\s+\w+\s*:[^{]*\{/.exec(code);
|
|
164
|
+
if (!header) return undefined;
|
|
165
|
+
let depth = 0;
|
|
166
|
+
for (let index = header.index + header[0].length - 1; index < code.length; index++) {
|
|
167
|
+
if (code[index] === '{') depth++;
|
|
168
|
+
else if (code[index] === '}' && --depth === 0) return index;
|
|
169
|
+
}
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
module.exports = { planMainApplication, withReactNativeLoaded, loadsReactNativeItself };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/** @typedef {import('./types').StepResult} StepResult */
|
|
5
|
+
|
|
6
|
+
const REQUIRE = "const { withApexNavigation } = require('@apexnative/navigation/metro');";
|
|
7
|
+
|
|
8
|
+
// The config the file exports: `module.exports = …;`, its last statement.
|
|
9
|
+
const EXPORT = /^module\.exports\s*=\s*([\s\S]+?);?\s*$/m;
|
|
10
|
+
|
|
11
|
+
const HOW_TO = `Wrap the config metro.config.js exports, so an edit updates the app by Fast Refresh instead of
|
|
12
|
+
reloading it:
|
|
13
|
+
|
|
14
|
+
${REQUIRE}
|
|
15
|
+
|
|
16
|
+
module.exports = withApexNavigation(mergeConfig(getDefaultConfig(__dirname), config));`;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* metro.config.js: the config it exports goes through withApexNavigation, which puts the navigation's Babel
|
|
20
|
+
* transformer in front of the app's own.
|
|
21
|
+
* @param {string} text
|
|
22
|
+
* @returns {StepResult}
|
|
23
|
+
*/
|
|
24
|
+
function planMetro(text) {
|
|
25
|
+
if (text.includes('withApexNavigation')) return { status: 'done', note: 'already set up' };
|
|
26
|
+
const found = EXPORT.exec(text);
|
|
27
|
+
// Only an export that ends the file: one in the middle may be changed by what comes after it.
|
|
28
|
+
if (!found || text.slice(found.index + found[0].length).trim() !== '') {
|
|
29
|
+
return { status: 'manual', note: 'changed by hand, see below', howTo: HOW_TO };
|
|
30
|
+
}
|
|
31
|
+
const exported = found[1].trim();
|
|
32
|
+
const before = text.slice(0, found.index);
|
|
33
|
+
const requires = [...before.matchAll(/^.*require\(.*\);?$/gm)];
|
|
34
|
+
const last = requires[requires.length - 1];
|
|
35
|
+
const head =
|
|
36
|
+
last === undefined
|
|
37
|
+
? `${REQUIRE}\n\n${before}`
|
|
38
|
+
: `${before.slice(0, last.index + last[0].length)}\n${REQUIRE}${before.slice(last.index + last[0].length)}`;
|
|
39
|
+
return {
|
|
40
|
+
status: 'change',
|
|
41
|
+
next: `${head}module.exports = withApexNavigation(${exported});\n`,
|
|
42
|
+
note: 'Fast Refresh for every edit',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = { planMetro, HOW_TO };
|