@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
|
@@ -1,13 +1,46 @@
|
|
|
1
1
|
#import "Image.h"
|
|
2
|
+
#import "ANNOptionImages.h"
|
|
2
3
|
|
|
3
4
|
@implementation Image
|
|
4
5
|
|
|
6
|
+
- (ANNImageSource *)source {
|
|
7
|
+
id value = self.value;
|
|
8
|
+
return [value isKindOfClass:ANNImageSource.class] ? value : nil;
|
|
9
|
+
}
|
|
10
|
+
|
|
5
11
|
- (UIImage *)get {
|
|
6
|
-
|
|
12
|
+
id value = self.value;
|
|
13
|
+
if ([value isKindOfClass:UIImage.class]) {
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
ANNImageSource *source = self.source;
|
|
17
|
+
return source ? [ANNOptionImages imageOf:source] : nil;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
- (BOOL)isSameValueAs:(ANNParam *)other {
|
|
21
|
+
if (other == self) {
|
|
22
|
+
return YES;
|
|
23
|
+
}
|
|
24
|
+
if (other.class != self.class) {
|
|
25
|
+
return NO;
|
|
26
|
+
}
|
|
27
|
+
ANNImageSource *source = self.source;
|
|
28
|
+
ANNImageSource *otherSource = ((Image *)other).source;
|
|
29
|
+
if (source || otherSource) {
|
|
30
|
+
return [source.sourceKey isEqualToString:otherSource.sourceKey];
|
|
31
|
+
}
|
|
32
|
+
return self.value == other.value;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
- (NSUInteger)valueHash {
|
|
36
|
+
ANNImageSource *source = self.source;
|
|
37
|
+
return source ? source.sourceKey.hash : (NSUInteger)(__bridge void *)self.value;
|
|
7
38
|
}
|
|
8
39
|
|
|
40
|
+
// A source that doesn't load is no image: the default then, as without a value.
|
|
9
41
|
- (UIImage *)withDefault:(UIImage *)defaultValue {
|
|
10
|
-
|
|
42
|
+
UIImage *image = self.hasValue ? self.get : nil;
|
|
43
|
+
return image ?: defaultValue;
|
|
11
44
|
}
|
|
12
45
|
|
|
13
46
|
@end
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
NS_ASSUME_NONNULL_BEGIN
|
|
4
4
|
|
|
5
|
-
/// Reads `key` of the options' JSON as
|
|
6
|
-
/// SF Symbol, else the fallback source; a source (a string, or an object with `uri`,
|
|
7
|
-
/// `height` and Metro's asset flag)
|
|
8
|
-
/// Metro asset. Remote addresses and arrays of sources are
|
|
9
|
-
/// Native log; it never throws.
|
|
5
|
+
/// Reads `key` of the options' JSON as the source of an image, which loads when an element shows it (`Image`):
|
|
6
|
+
/// `{ system, fallback? }` is an SF Symbol, else the fallback source; a source (a string, or an object with `uri`,
|
|
7
|
+
/// `bundle`, `scale`, `width`, `height` and Metro's asset flag) is a file, an asset of the app's bundle, a `data:`
|
|
8
|
+
/// address, or in development a Metro asset. Remote addresses and arrays of sources are no image, with an error in the
|
|
9
|
+
/// React Native log; it never throws.
|
|
10
10
|
@interface ImageParser : NSObject
|
|
11
11
|
|
|
12
12
|
+ (Image *)parse:(nullable NSDictionary *)json key:(NSString *)key;
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
#import "ANNOptionsReader.h"
|
|
3
3
|
#import <React/RCTConvert.h>
|
|
4
4
|
#import <React/RCTLog.h>
|
|
5
|
-
#import <React/RCTUtils.h>
|
|
6
5
|
|
|
7
6
|
@implementation ImageParser
|
|
8
7
|
|
|
@@ -12,10 +11,10 @@
|
|
|
12
11
|
return [[Image alloc] initWithValue:nil];
|
|
13
12
|
}
|
|
14
13
|
NSString *path = [ANNOptionsReader pathOfKey:key];
|
|
15
|
-
return [[Image alloc] initWithValue:[self
|
|
14
|
+
return [[Image alloc] initWithValue:[self sourceOf:value path:path]];
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
+ (
|
|
17
|
+
+ (ANNImageSource *)sourceOf:(id)value path:(NSString *)path {
|
|
19
18
|
if ([value isKindOfClass:NSArray.class]) {
|
|
20
19
|
RCTLogError(@"[ApexNavigation] the image of '%@' is a list of sources, which options don't support: give "
|
|
21
20
|
@"one source",
|
|
@@ -23,27 +22,28 @@
|
|
|
23
22
|
return nil;
|
|
24
23
|
}
|
|
25
24
|
if ([value isKindOfClass:NSDictionary.class] && value[@"system"]) {
|
|
26
|
-
return [self
|
|
25
|
+
return [self symbolOf:value path:path];
|
|
27
26
|
}
|
|
28
27
|
if (![value isKindOfClass:NSString.class] && ![value isKindOfClass:NSDictionary.class]) {
|
|
29
28
|
return nil;
|
|
30
29
|
}
|
|
31
|
-
return [self
|
|
30
|
+
return [self addressOf:value path:path];
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
// An SF Symbol; a name the system doesn't have takes the fallback source, read the same way.
|
|
35
|
-
+ (
|
|
34
|
+
+ (ANNImageSource *)symbolOf:(NSDictionary *)value path:(NSString *)path {
|
|
36
35
|
id name = value[@"system"];
|
|
37
|
-
UIImage *image = [name isKindOfClass:NSString.class] ? [UIImage systemImageNamed:name] : nil;
|
|
38
|
-
if (image) {
|
|
39
|
-
return image;
|
|
40
|
-
}
|
|
41
36
|
id fallback = value[@"fallback"];
|
|
42
|
-
|
|
37
|
+
ANNImageSource *fallbackSource =
|
|
38
|
+
fallback && fallback != NSNull.null ? [self sourceOf:fallback path:path] : nil;
|
|
39
|
+
if (![name isKindOfClass:NSString.class] || [name length] == 0) {
|
|
40
|
+
return fallbackSource;
|
|
41
|
+
}
|
|
42
|
+
return [ANNImageSource symbolNamed:name fallback:fallbackSource];
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
// A resolved source
|
|
46
|
-
+ (
|
|
45
|
+
// A resolved source: its address and the fields its scale comes from.
|
|
46
|
+
+ (ANNImageSource *)addressOf:(id)source path:(NSString *)path {
|
|
47
47
|
NSDictionary *fields = [source isKindOfClass:NSDictionary.class] ? source : nil;
|
|
48
48
|
id address = fields ? (fields[@"uri"] ?: fields[@"url"]) : source;
|
|
49
49
|
if (![address isKindOfClass:NSString.class] || [address length] == 0) {
|
|
@@ -56,48 +56,30 @@
|
|
|
56
56
|
}
|
|
57
57
|
NSURL *url = [RCTConvert NSURL:address];
|
|
58
58
|
NSString *scheme = url.scheme.lowercaseString;
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
id packagerAsset = fields[@"__packager_asset"];
|
|
60
|
+
BOOL metroAsset = ANNJSONIsBoolean(packagerAsset) && [packagerAsset boolValue];
|
|
61
|
+
ANNImageSourceKind kind;
|
|
61
62
|
if ([scheme isEqualToString:@"file"]) {
|
|
62
|
-
|
|
63
|
+
kind = ANNImageSourceKindFile;
|
|
63
64
|
} else if ([scheme isEqualToString:@"data"]) {
|
|
64
|
-
|
|
65
|
+
kind = ANNImageSourceKindData;
|
|
65
66
|
} else if (([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]) && metroAsset) {
|
|
66
|
-
|
|
67
|
-
image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
|
|
67
|
+
kind = ANNImageSourceKindMetro;
|
|
68
68
|
} else {
|
|
69
69
|
RCTLogError(@"[ApexNavigation] the image of '%@' is not loaded: remote images are not supported in options "
|
|
70
70
|
@"(%@)",
|
|
71
71
|
path, address);
|
|
72
72
|
return nil;
|
|
73
73
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
+ (UIImage *)image:(UIImage *)image scaledBy:(NSDictionary *)fields {
|
|
84
|
-
id scaleValue = fields[@"scale"];
|
|
85
|
-
id widthValue = fields[@"width"];
|
|
86
|
-
id heightValue = fields[@"height"];
|
|
87
|
-
CGFloat scale = ANNJSONIsNumber(scaleValue) ? [scaleValue doubleValue] : 0;
|
|
88
|
-
CGFloat width = ANNJSONIsNumber(widthValue) ? [widthValue doubleValue] : 0;
|
|
89
|
-
CGFloat height = ANNJSONIsNumber(heightValue) ? [heightValue doubleValue] : 0;
|
|
90
|
-
if (scale <= 0 && width > 0 && image.CGImage) {
|
|
91
|
-
scale = CGImageGetWidth(image.CGImage) / width;
|
|
92
|
-
}
|
|
93
|
-
if (scale > 0 && image.CGImage && scale != image.scale) {
|
|
94
|
-
image = [UIImage imageWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
|
|
95
|
-
}
|
|
96
|
-
if (width > 0 && height > 0 && !CGSizeEqualToSize(image.size, CGSizeMake(width, height))) {
|
|
97
|
-
RCTLogInfo(@"[ApexNavigation] an image of the options is %@, its source says %@",
|
|
98
|
-
NSStringFromCGSize(image.size), NSStringFromCGSize(CGSizeMake(width, height)));
|
|
99
|
-
}
|
|
100
|
-
return image;
|
|
74
|
+
id scale = fields[@"scale"];
|
|
75
|
+
id width = fields[@"width"];
|
|
76
|
+
id height = fields[@"height"];
|
|
77
|
+
return [ANNImageSource sourceOfKind:kind
|
|
78
|
+
url:url
|
|
79
|
+
address:address
|
|
80
|
+
scale:ANNJSONIsNumber(scale) ? [scale doubleValue] : 0
|
|
81
|
+
width:ANNJSONIsNumber(width) ? [width doubleValue] : 0
|
|
82
|
+
height:ANNJSONIsNumber(height) ? [height doubleValue] : 0];
|
|
101
83
|
}
|
|
102
84
|
|
|
103
85
|
@end
|
|
@@ -9,6 +9,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
9
9
|
* When the scene connects, the navigation window moves into it. URLs, user activities and foreground/background
|
|
10
10
|
* changes that UIKit now delivers to the scene are forwarded to the app delegate's usual methods, so
|
|
11
11
|
* the deep links (`dispatchDeepLinkURL:`) and app delegate overrides keep working.
|
|
12
|
+
*
|
|
13
|
+
* The app's own scene delegate can extend it (`class SceneDelegate: ANNSceneDelegate {}`, which `setup` makes of React
|
|
14
|
+
* Native 0.88's template); a method it overrides calls `super`.
|
|
12
15
|
*/
|
|
13
16
|
@interface ANNSceneDelegate : UIResponder <UIWindowSceneDelegate>
|
|
14
17
|
|
|
@@ -37,7 +37,7 @@ NS_SWIFT_NAME(NativeScreenContext)
|
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
* Runs a command of the navigation from this screen in JS, as `useNavigation()` of a React screen does: push, pop,
|
|
40
|
-
* popTo, popToRoot, showInColumn, showModal, dismiss, showOverlay,
|
|
40
|
+
* popTo, popToRoot, showInColumn, showModal, dismiss, showOverlay, setOptions, selectTab, setTabBadge.
|
|
41
41
|
* `arguments` are those of the JS command; `completion` gets what it resolved with.
|
|
42
42
|
*
|
|
43
43
|
* ```swift
|
package/ios/RECIPES.md
CHANGED
|
@@ -16,9 +16,14 @@ you do exactly that; the map is `ios/CLAUDE.md`.
|
|
|
16
16
|
what the merge names) and in `applyDefaultOptionsChange:`. A system-UI option also goes into
|
|
17
17
|
`+[ANNSystemUI groupsNamedBy:onlyRead:]`; a bar-placement option into `ANNOptionsChangeScreenBars`.
|
|
18
18
|
4. **The cache.** Never invalidate by hand. Own options change through `ANNNodeHelper` (`mergeOwnOptions:`,
|
|
19
|
-
`changeOwnOptions:`)
|
|
20
|
-
`+[
|
|
21
|
-
|
|
19
|
+
`changeOwnOptions:`), the user layer through `setUserChoice:forKey:`, and defaults through
|
|
20
|
+
`+[ANNDefaultOptions setCurrent:]`; all call `+[ANNOptionsCache optionsChanged]`. `changeOwnOptions:` is for what
|
|
21
|
+
the core keeps of the app's merges. A presenter or module that keeps a choice of the user (a toggle, a menu check,
|
|
22
|
+
a scope) puts an `ANNUserChoice` into the node's user layer under a key of its own: its `apply` block writes the
|
|
23
|
+
choice by identity (a button or item by its id) on a copy, its `merged` block says when the app's merge takes it
|
|
24
|
+
away, by Android's rules (`UserChoices.yieldTo`): a value other than the app had there (the own options', else the
|
|
25
|
+
node's resolution before the merge), or what the choice is about gone from the resolution after it. Never into the
|
|
26
|
+
options in place.
|
|
22
27
|
5. **Android** reads the same JSON and has unit tests of parsing and merging; the iOS side has none (see Checks in `ios/CLAUDE.md`).
|
|
23
28
|
6. **The rule:** an option does what its name promises, with the same meaning on both platforms
|
|
24
29
|
(`.claude/rules/general.md`, `.claude/rules/options.md`). A platform that can't, says so in the JSDoc.
|
|
@@ -34,8 +39,10 @@ you do exactly that; the map is `ios/CLAUDE.md`.
|
|
|
34
39
|
4. **The layout check:** a new node type goes into `ANNLayoutType` and `ANNLayoutReader` (its place, its children), and
|
|
35
40
|
gets a maker in `ANNLayoutFactory`.
|
|
36
41
|
5. **Error texts** come from `ANNErrorTexts`, one sentence per case, the same as Android; a text deep in a maker is
|
|
37
|
-
thrown with `+[ANNErrorTexts rejection:]`.
|
|
42
|
+
thrown with `+[ANNErrorTexts rejection:]`. A new text goes into `src/interfaces/contract/errors.json`, and
|
|
43
|
+
`node scripts/contract.mjs` makes `ANNErrorTexts` (and Android's `ErrorTexts`) from it; never edit them by hand.
|
|
38
44
|
6. **The answer:** end through `ANNAppearanceDispatcher` (`endTransitionHiding:…answer:value:`) or call
|
|
39
|
-
`-[ANNCommandAnswer resolve:]`; the state and `ANN.CommandCompleted` follow by themselves
|
|
40
|
-
|
|
45
|
+
`-[ANNCommandAnswer resolve:]`; the state and `ANN.CommandCompleted` follow by themselves as `ANNCommandContract`
|
|
46
|
+
says. A new command with a promise gets its entry in `src/interfaces/contract/commands.json` (what it resolves
|
|
47
|
+
with, `state`, `completed`), then `node scripts/contract.mjs`.
|
|
41
48
|
7. **Android** gets the same command; its tests check the texts.
|
|
@@ -8,29 +8,9 @@
|
|
|
8
8
|
#import "ANNSurfaceHostingView.h"
|
|
9
9
|
#import <React/RCTFabricSurface.h>
|
|
10
10
|
#import <React/RCTSurfacePresenter.h>
|
|
11
|
-
#import <React/RCTSurfaceStage.h>
|
|
12
11
|
#import <React/RCTSurfaceView.h>
|
|
13
12
|
#import <ReactCommon/RCTHost.h>
|
|
14
13
|
|
|
15
|
-
// A surface that still starts can't be stopped yet: it is checked this often, at most this many times (5 s), and then
|
|
16
|
-
// stopped anyway.
|
|
17
|
-
static const NSTimeInterval ANNSurfaceStopCheckInterval = 0.05;
|
|
18
|
-
static const NSUInteger ANNSurfaceStopCheckLimit = 100;
|
|
19
|
-
|
|
20
|
-
// Stops `surface` once it runs. The block holds the surface and the view that hosts it until then: a hosting view
|
|
21
|
-
// released earlier would stop the surface in its `dealloc`, maybe off the main queue.
|
|
22
|
-
static void ANNStopSurfaceWhenRunning(RCTFabricSurface *surface, UIView *hostingView,
|
|
23
|
-
NSUInteger checksLeft) {
|
|
24
|
-
if (RCTSurfaceStageIsRunning(surface.stage) || checksLeft == 0) {
|
|
25
|
-
[surface stop];
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
int64_t delay = (int64_t)(ANNSurfaceStopCheckInterval * NSEC_PER_SEC);
|
|
29
|
-
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay), dispatch_get_main_queue(), ^{
|
|
30
|
-
ANNStopSurfaceWhenRunning(surface, hostingView, checksLeft - 1);
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
14
|
@interface ANNReactView () <RCTSurfacePresenterObserver, ANNScreenReadinessListener>
|
|
35
15
|
@end
|
|
36
16
|
|
|
@@ -359,14 +339,15 @@ static void ANNStopSurfaceWhenRunning(RCTFabricSurface *surface, UIView *hosting
|
|
|
359
339
|
_reactViewReadyBlock = nil;
|
|
360
340
|
_mountHandlers = nil;
|
|
361
341
|
[_contentDidMountHandlers removeAllObjects];
|
|
362
|
-
|
|
363
|
-
if (
|
|
342
|
+
ANNSurfaceHostingView *hostingView = _hostingView;
|
|
343
|
+
if (_surface && hostingView) {
|
|
364
344
|
// On the next turn of the main queue: a destroy that runs inside React Native's mounting (a wait that ends in
|
|
365
345
|
// a mount, a root that replaces at once) would stop the surface there, React Native would drop its last
|
|
366
|
-
// transaction and recycle its root view with the old content still in it, to show in a later screen.
|
|
367
|
-
|
|
346
|
+
// transaction and recycle its root view with the old content still in it, to show in a later screen. The
|
|
347
|
+
// hosting view stops the surface then, or at its start when it doesn't run yet; the block keeps the hosting
|
|
348
|
+
// view, and with it the surface, until it asks.
|
|
368
349
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
369
|
-
|
|
350
|
+
[hostingView stopSurfaceWhenRunning];
|
|
370
351
|
});
|
|
371
352
|
}
|
|
372
353
|
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
#import "ANNSafeAreaViewComponentView.h"
|
|
2
|
-
#import "
|
|
2
|
+
#import "ANNScreenEnvironment.h"
|
|
3
3
|
#import "ANNScreenReadiness.h"
|
|
4
4
|
#import "../cpp/react/renderer/components/ApexNavigationSpec/ANNSafeAreaViewComponentDescriptor.h"
|
|
5
5
|
#import <React/RCTConversions.h>
|
|
6
6
|
|
|
7
7
|
using namespace facebook::react;
|
|
8
8
|
|
|
9
|
+
@interface ANNSafeAreaViewComponentView () <ANNScreenPaddingListener>
|
|
10
|
+
@end
|
|
11
|
+
|
|
9
12
|
@implementation ANNSafeAreaViewComponentView {
|
|
10
13
|
ANNSafeAreaViewShadowNode::ConcreteState::Shared _state;
|
|
11
14
|
NSString *_screenId;
|
|
@@ -22,21 +25,13 @@ using namespace facebook::react;
|
|
|
22
25
|
if (self = [super initWithFrame:frame]) {
|
|
23
26
|
static const auto defaultProps = std::make_shared<const ANNSafeAreaViewProps>();
|
|
24
27
|
_props = defaultProps;
|
|
25
|
-
[NSNotificationCenter.defaultCenter addObserver:self
|
|
26
|
-
selector:@selector(paddingDidChange:)
|
|
27
|
-
name:ANNScreenSafeAreaPaddingDidChangeNotification
|
|
28
|
-
object:nil];
|
|
29
28
|
}
|
|
30
29
|
return self;
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
- (void)dealloc {
|
|
34
|
-
[NSNotificationCenter.defaultCenter removeObserver:self];
|
|
35
|
-
}
|
|
36
|
-
|
|
37
32
|
- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps {
|
|
38
33
|
const auto &newProps = static_cast<const ANNSafeAreaViewProps &>(*props);
|
|
39
|
-
|
|
34
|
+
[self listenToScreenId:RCTNSStringFromStringNilIfEmpty(newProps.screenId)];
|
|
40
35
|
// The screen's readiness comes from this view, never from its root's children.
|
|
41
36
|
if (_screenId != nil) {
|
|
42
37
|
[ANNScreenReadiness screenHasSafeAreaView:_screenId];
|
|
@@ -70,18 +65,33 @@ using namespace facebook::react;
|
|
|
70
65
|
[self applyPadding];
|
|
71
66
|
}
|
|
72
67
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
68
|
+
// The view hears the padding changes of its screen only. It listens before it applies the padding it has, at each
|
|
69
|
+
// props, so a change between the two can't be missed.
|
|
70
|
+
- (void)listenToScreenId:(nullable NSString *)screenId {
|
|
71
|
+
if ((screenId == nil && _screenId == nil) || [screenId isEqualToString:_screenId]) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (_screenId != nil) {
|
|
75
|
+
[ANNScreenEnvironment removePaddingListener:self forScreenId:_screenId];
|
|
76
|
+
}
|
|
77
|
+
_screenId = screenId;
|
|
78
|
+
if (screenId != nil) {
|
|
79
|
+
[ANNScreenEnvironment addPaddingListener:self forScreenId:screenId];
|
|
76
80
|
}
|
|
77
81
|
}
|
|
78
82
|
|
|
83
|
+
#pragma mark - ANNScreenPaddingListener
|
|
84
|
+
|
|
85
|
+
- (void)screenPaddingDidChange {
|
|
86
|
+
[self applyPadding];
|
|
87
|
+
}
|
|
88
|
+
|
|
79
89
|
// The padding of the screen goes to the state, which lays the view out with it.
|
|
80
90
|
- (void)applyPadding {
|
|
81
91
|
if (_state == nullptr || _screenId == nil) {
|
|
82
92
|
return;
|
|
83
93
|
}
|
|
84
|
-
UIEdgeInsets padding = [
|
|
94
|
+
UIEdgeInsets padding = [ANNScreenEnvironment paddingForScreenId:_screenId];
|
|
85
95
|
EdgeInsets insets{.left = (Float)padding.left,
|
|
86
96
|
.top = (Float)padding.top,
|
|
87
97
|
.right = (Float)padding.right,
|
|
@@ -118,8 +128,8 @@ using namespace facebook::react;
|
|
|
118
128
|
|
|
119
129
|
// The screen renders its content once this view is laid out in its place with a size, as
|
|
120
130
|
// react-native-safe-area-context does: a list that is there before the first layout of the top bar
|
|
121
|
-
// makes UIKit start the large title collapsed.
|
|
122
|
-
//
|
|
131
|
+
// makes UIKit start the large title collapsed. A tab rendered before it shows lays out in the
|
|
132
|
+
// tabs' view, unseen, and renders its content there.
|
|
123
133
|
- (void)sendReadyIfLaidOut {
|
|
124
134
|
if (_readySent || _eventEmitter == nullptr || self.superview == nil) {
|
|
125
135
|
return;
|
|
@@ -144,7 +154,8 @@ using namespace facebook::react;
|
|
|
144
154
|
- (void)prepareForRecycle {
|
|
145
155
|
[super prepareForRecycle];
|
|
146
156
|
_state.reset();
|
|
147
|
-
|
|
157
|
+
// A recycled view gets its next screen's id with its next props.
|
|
158
|
+
[self listenToScreenId:nil];
|
|
148
159
|
_readySent = NO;
|
|
149
160
|
_contentRenderedSent = NO;
|
|
150
161
|
_contentRendered = NO;
|
|
@@ -8,10 +8,24 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
8
8
|
/// every change on.
|
|
9
9
|
@interface ANNSurfaceHostingView : RCTSurfaceHostingView
|
|
10
10
|
|
|
11
|
+
/// A size transition of the window (a rotation, a new window size) runs until its coordinator completes. Meanwhile React
|
|
12
|
+
/// content takes its new size without animation (`layOutContent:`). Each call ends with its own transition; main queue.
|
|
13
|
+
+ (void)followSizeTransition:(id<UIViewControllerTransitionCoordinator>)coordinator;
|
|
14
|
+
|
|
15
|
+
/// Runs a layout that gives React content a new size: without animation while a size transition runs, as it is
|
|
16
|
+
/// otherwise. Main queue.
|
|
17
|
+
+ (void)layOutContent:(void (^)(void))layout;
|
|
18
|
+
|
|
11
19
|
/// Called at each mount of the hosted surface: after a change of the surface's size, the first one lays the surface
|
|
12
20
|
/// out again, so a render that was on its way during the change doesn't keep the old size's layout.
|
|
13
21
|
- (void)surfaceDidMount;
|
|
14
22
|
|
|
23
|
+
/// The screen went: the hosted surface stops as soon as it runs, on the main queue. A surface that runs already stops
|
|
24
|
+
/// at once; one that doesn't run yet stops at its change to running (`surface:didChangeStage:`). Until then this view
|
|
25
|
+
/// and its surface are kept, so the core gives them up on the main queue. A surface that hasn't started after 5 s is
|
|
26
|
+
/// let go, and stops if it ever starts later. Once; main queue.
|
|
27
|
+
- (void)stopSurfaceWhenRunning;
|
|
28
|
+
|
|
15
29
|
@end
|
|
16
30
|
|
|
17
31
|
NS_ASSUME_NONNULL_END
|
|
@@ -1,9 +1,52 @@
|
|
|
1
1
|
#import "ANNSurfaceHostingView.h"
|
|
2
|
+
#import "ANNAssert.h"
|
|
2
3
|
#import <React/RCTFabricSurface.h>
|
|
4
|
+
#import <objc/runtime.h>
|
|
5
|
+
|
|
6
|
+
// How long a gone screen's surface that doesn't run yet is kept for its stop. The host starts a surface through a weak
|
|
7
|
+
// reference once its JavaScript ran, so a surface let go before that, which nothing else holds, goes away unstarted.
|
|
8
|
+
static const NSTimeInterval ANNSurfaceStartWaitLimit = 5.0;
|
|
9
|
+
static const void *ANNSurfaceStopperKey = &ANNSurfaceStopperKey;
|
|
10
|
+
|
|
11
|
+
// The hosting views whose surface stops at its start; each keeps its surface. Main queue.
|
|
12
|
+
static NSMutableSet<ANNSurfaceHostingView *> *ANNHostingViewsStoppingAtStart;
|
|
13
|
+
|
|
14
|
+
// The size transitions of the window that run now. Main queue.
|
|
15
|
+
static NSInteger ANNSizeTransitionCount;
|
|
16
|
+
|
|
17
|
+
// The delegate of a surface its hosting view let go at the limit: the surface keeps it, and it keeps nothing, so
|
|
18
|
+
// neither holds the other alive. A surface that something else still starts (a start already on its way holds its
|
|
19
|
+
// surface; React Native restarts every surface it knows after a reload, holding it) stops at once, instead of running
|
|
20
|
+
// with no screen and going away running, which leaves its React tree registered.
|
|
21
|
+
@interface ANNSurfaceStopper : NSObject <RCTSurfaceDelegate>
|
|
22
|
+
@end
|
|
23
|
+
|
|
24
|
+
@implementation ANNSurfaceStopper
|
|
25
|
+
|
|
26
|
+
// React Native's delegate method names the deprecated `RCTSurface`; the surface is an `RCTFabricSurface`.
|
|
27
|
+
#pragma clang diagnostic push
|
|
28
|
+
#pragma clang diagnostic ignored "-Wdeprecated"
|
|
29
|
+
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
|
30
|
+
- (void)surface:(RCTSurface *)surface didChangeStage:(RCTSurfaceStage)stage {
|
|
31
|
+
if (!RCTSurfaceStageIsRunning(stage)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
// The start tells this off the main queue, before it ends: the stop goes on the main queue, the block keeping the
|
|
35
|
+
// surface until then.
|
|
36
|
+
id<RCTSurfaceProtocol> startedSurface = (id<RCTSurfaceProtocol>)surface;
|
|
37
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
38
|
+
[startedSurface stop];
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
#pragma clang diagnostic pop
|
|
42
|
+
|
|
43
|
+
@end
|
|
3
44
|
|
|
4
45
|
@implementation ANNSurfaceHostingView {
|
|
5
46
|
// The surface was given a new size since its last mount.
|
|
6
47
|
BOOL _surfaceSizeChanged;
|
|
48
|
+
// The screen went: the surface stops each time it runs. Main queue.
|
|
49
|
+
BOOL _stopsWhenRunning;
|
|
7
50
|
}
|
|
8
51
|
|
|
9
52
|
// React Native 0.87 posts the hosting view's traits as the app's scheme from here (`RCTSurfaceHostingView.mm`). On
|
|
@@ -20,6 +63,28 @@
|
|
|
20
63
|
|
|
21
64
|
#pragma mark - The surface's size
|
|
22
65
|
|
|
66
|
+
// UIKit lays the screens out inside the animation of a rotation or a new window size, and React Native commits and
|
|
67
|
+
// mounts the new layout synchronously inside the layout that gives it the size: every frame of its views animated
|
|
68
|
+
// from the old size to the new one, and what a view draws itself (an SVG, a glass view, text) was drawn once at the new
|
|
69
|
+
// size and stretched along that animation. During such a transition the content takes its new layout at once; the
|
|
70
|
+
// hosting view itself still follows the animation. Other animated size changes (a sheet's detent, a split view's
|
|
71
|
+
// column) keep the content's frames animated, so content pinned to the moving edge rides along with it.
|
|
72
|
+
+ (void)followSizeTransition:(id<UIViewControllerTransitionCoordinator>)coordinator {
|
|
73
|
+
ANNSizeTransitionCount++;
|
|
74
|
+
[coordinator animateAlongsideTransition:nil
|
|
75
|
+
completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
|
|
76
|
+
ANNSizeTransitionCount--;
|
|
77
|
+
}];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
+ (void)layOutContent:(void (^)(void))layout {
|
|
81
|
+
if (ANNSizeTransitionCount > 0) {
|
|
82
|
+
[UIView performWithoutAnimation:layout];
|
|
83
|
+
} else {
|
|
84
|
+
layout();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
23
88
|
// React Native gives the surface its size here. A size change is noted for the next mount (see below). The note is
|
|
24
89
|
// put aside during the call: the change's own commit mounts inside it and must not take an earlier note, or a size
|
|
25
90
|
// that changes every frame (a sheet dragged between detents, a window resized) would lay out three times a frame. A
|
|
@@ -30,7 +95,9 @@
|
|
|
30
95
|
CGSize maximumSize = surface.maximumSize;
|
|
31
96
|
BOOL sizeChangedBefore = _surfaceSizeChanged;
|
|
32
97
|
_surfaceSizeChanged = NO;
|
|
33
|
-
[
|
|
98
|
+
[ANNSurfaceHostingView layOutContent:^{
|
|
99
|
+
[super layoutSubviews];
|
|
100
|
+
}];
|
|
34
101
|
BOOL sizeChanged = surface && (!CGSizeEqualToSize(minimumSize, surface.minimumSize) ||
|
|
35
102
|
!CGSizeEqualToSize(maximumSize, surface.maximumSize));
|
|
36
103
|
_surfaceSizeChanged = sizeChanged || sizeChangedBefore;
|
|
@@ -60,6 +127,82 @@
|
|
|
60
127
|
[surface setMinimumSize:minimumSize maximumSize:maximumSize];
|
|
61
128
|
}
|
|
62
129
|
|
|
130
|
+
#pragma mark - The stop
|
|
131
|
+
|
|
132
|
+
// `RCTFabricSurface stop` does nothing while the surface doesn't run, and the host starts a surface later, off the main
|
|
133
|
+
// queue: a screen can go before that. Its surface then stops at its change to running. This view is kept until then,
|
|
134
|
+
// with its surface: released earlier, it would stop the surface in its `dealloc`, maybe off the main queue.
|
|
135
|
+
- (void)stopSurfaceWhenRunning {
|
|
136
|
+
ANNAssertMainQueue();
|
|
137
|
+
if (_stopsWhenRunning) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
_stopsWhenRunning = YES;
|
|
141
|
+
RCTFabricSurface *surface = [self fabricSurface];
|
|
142
|
+
if (!surface) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (RCTSurfaceStageIsRunning(surface.stage)) {
|
|
146
|
+
[surface stop];
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (!ANNHostingViewsStoppingAtStart) {
|
|
150
|
+
ANNHostingViewsStoppingAtStart = [NSMutableSet new];
|
|
151
|
+
}
|
|
152
|
+
[ANNHostingViewsStoppingAtStart addObject:self];
|
|
153
|
+
__weak ANNSurfaceHostingView *weakSelf = self;
|
|
154
|
+
int64_t delay = (int64_t)(ANNSurfaceStartWaitLimit * NSEC_PER_SEC);
|
|
155
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay), dispatch_get_main_queue(), ^{
|
|
156
|
+
[weakSelf letSurfaceGo];
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// The surface tells its stage off the main queue, from its start and its stop. React Native's hosting view follows it
|
|
161
|
+
// as before; a gone screen's surface that starts stops on the next turn of the main queue, once its start ended. The
|
|
162
|
+
// block keeps this view, and with it the surface, until then, so their last release is on the main queue.
|
|
163
|
+
#pragma clang diagnostic push
|
|
164
|
+
#pragma clang diagnostic ignored "-Wdeprecated"
|
|
165
|
+
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
|
166
|
+
- (void)surface:(RCTSurface *)surface didChangeStage:(RCTSurfaceStage)stage {
|
|
167
|
+
[super surface:surface didChangeStage:stage];
|
|
168
|
+
if (!RCTSurfaceStageIsRunning(stage)) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
172
|
+
[self stopSurfaceIfAsked];
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
#pragma clang diagnostic pop
|
|
176
|
+
|
|
177
|
+
- (void)stopSurfaceIfAsked {
|
|
178
|
+
if (!_stopsWhenRunning) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
RCTFabricSurface *surface = [self fabricSurface];
|
|
182
|
+
if (surface && RCTSurfaceStageIsRunning(surface.stage)) {
|
|
183
|
+
[surface stop];
|
|
184
|
+
}
|
|
185
|
+
[ANNHostingViewsStoppingAtStart removeObject:self];
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// The limit: the surface hasn't started. It gets a delegate of its own that stops it at any later start, and this
|
|
189
|
+
// view lets it go. The delegate changes before the check: a start told before the change reaches this view, which
|
|
190
|
+
// stops the surface (its block keeps the view); one told after it reaches the new delegate.
|
|
191
|
+
- (void)letSurfaceGo {
|
|
192
|
+
if (![ANNHostingViewsStoppingAtStart containsObject:self]) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
RCTFabricSurface *surface = [self fabricSurface];
|
|
196
|
+
ANNSurfaceStopper *stopper = [ANNSurfaceStopper new];
|
|
197
|
+
objc_setAssociatedObject(surface, ANNSurfaceStopperKey, stopper,
|
|
198
|
+
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
199
|
+
surface.delegate = stopper;
|
|
200
|
+
if (RCTSurfaceStageIsRunning(surface.stage)) {
|
|
201
|
+
[surface stop];
|
|
202
|
+
}
|
|
203
|
+
[ANNHostingViewsStoppingAtStart removeObject:self];
|
|
204
|
+
}
|
|
205
|
+
|
|
63
206
|
- (nullable RCTFabricSurface *)fabricSurface {
|
|
64
207
|
id surface = self.surface;
|
|
65
208
|
return [surface isKindOfClass:RCTFabricSurface.class] ? surface : nil;
|