@apexnative/navigation 1.0.0-alpha.1 → 1.0.0-alpha.11
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 +132 -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/ArrangementDefinition.kt +9 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementPlanner.kt +20 -15
- 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/arrangement.md +17 -1
- 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 +61 -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 +195 -21
- 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 +34 -0
- package/ios/Layouts/Screen/ANNScreenSettling.mm +171 -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/arrangement.js +5 -2
- package/lib/module/api/screens/arrangement.js.map +1 -1
- 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/arrangement.d.ts +12 -2
- package/lib/typescript/api/screens/arrangement.d.ts.map +1 -1
- 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/arrangement.ts +17 -4
- 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,6 +1,7 @@
|
|
|
1
1
|
#import "ANNSheetPresenter.h"
|
|
2
2
|
#import "ANNModalSizePresenter.h"
|
|
3
3
|
#import "ANNReactView.h"
|
|
4
|
+
#import "ANNUtils.h"
|
|
4
5
|
#import "UIViewController+LayoutProtocol.h"
|
|
5
6
|
#import <React/RCTLog.h>
|
|
6
7
|
#import <objc/runtime.h>
|
|
@@ -53,7 +54,7 @@ static NSString *const ANNContentDetent = @"content";
|
|
|
53
54
|
+ (void)applyOptions:(ANNSheetOptions *)options toSheet:(UISheetPresentationController *)sheet {
|
|
54
55
|
if (options.detents) {
|
|
55
56
|
NSMutableArray<UISheetPresentationControllerDetent *> *detents = [NSMutableArray new];
|
|
56
|
-
for (id value in options.detents) {
|
|
57
|
+
for (id value in [self sortedDetents:options.detents ofSheet:sheet]) {
|
|
57
58
|
UISheetPresentationControllerDetent *detent = [self detentFor:value ofSheet:sheet];
|
|
58
59
|
if (detent) {
|
|
59
60
|
[detents addObject:detent];
|
|
@@ -81,6 +82,85 @@ static NSString *const ANNContentDetent = @"content";
|
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
84
|
|
|
85
|
+
// UIKit wants the detents once each, from the lowest to the highest: it takes the last for the largest and closes the
|
|
86
|
+
// sheet on a drag down from the first. The options may give them in any order and more than once; the first of a
|
|
87
|
+
// repeat stays, and detents of the same height keep their order.
|
|
88
|
+
+ (NSArray *)sortedDetents:(NSArray *)values ofSheet:(UISheetPresentationController *)sheet {
|
|
89
|
+
NSMutableArray *detents = [NSMutableArray new];
|
|
90
|
+
NSMutableSet<NSString *> *identifiers = [NSMutableSet new];
|
|
91
|
+
for (id value in values) {
|
|
92
|
+
NSString *identifier = [self identifierFor:value];
|
|
93
|
+
if (identifier && ![identifiers containsObject:identifier]) {
|
|
94
|
+
[identifiers addObject:identifier];
|
|
95
|
+
[detents addObject:value];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
CGFloat maximum = [self maximumDetentHeightOf:sheet];
|
|
99
|
+
return [detents sortedArrayWithOptions:NSSortStable
|
|
100
|
+
usingComparator:^NSComparisonResult(id a, id b) {
|
|
101
|
+
return [self compareHeightOf:a
|
|
102
|
+
with:b
|
|
103
|
+
maximum:maximum
|
|
104
|
+
ofSheet:sheet];
|
|
105
|
+
}];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// The content of a sheet sized to it changed its height, and with it maybe its place among the other detents.
|
|
109
|
+
+ (void)sortDetentsOfSheet:(UISheetPresentationController *)sheet API_AVAILABLE(ios(16.0)) {
|
|
110
|
+
CGFloat maximum = [self maximumDetentHeightOf:sheet];
|
|
111
|
+
NSArray<UISheetPresentationControllerDetent *> *detents = sheet.detents;
|
|
112
|
+
NSArray<UISheetPresentationControllerDetent *> *sorted = [detents
|
|
113
|
+
sortedArrayWithOptions:NSSortStable
|
|
114
|
+
usingComparator:^NSComparisonResult(UISheetPresentationControllerDetent *a,
|
|
115
|
+
UISheetPresentationControllerDetent *b) {
|
|
116
|
+
return [self compareHeightOf:[self detentForIdentifier:a.identifier]
|
|
117
|
+
with:[self detentForIdentifier:b.identifier]
|
|
118
|
+
maximum:maximum
|
|
119
|
+
ofSheet:sheet];
|
|
120
|
+
}];
|
|
121
|
+
if (![sorted isEqualToArray:detents]) {
|
|
122
|
+
sheet.detents = sorted;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
+ (NSComparisonResult)compareHeightOf:(id)a
|
|
127
|
+
with:(id)b
|
|
128
|
+
maximum:(CGFloat)maximum
|
|
129
|
+
ofSheet:(UISheetPresentationController *)sheet {
|
|
130
|
+
CGFloat heightA = [self heightOf:a maximum:maximum ofSheet:sheet];
|
|
131
|
+
CGFloat heightB = [self heightOf:b maximum:maximum ofSheet:sheet];
|
|
132
|
+
return heightA < heightB ? NSOrderedAscending
|
|
133
|
+
: heightA > heightB ? NSOrderedDescending : NSOrderedSame;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// The height a detent of the options stands at, to sort them, as its resolver gives it: 'medium' half of the largest
|
|
137
|
+
// height (UIKit's is about half), 'large' all of it, a height capped at it, 'content' the content's height now, all of
|
|
138
|
+
// it while the content isn't measured.
|
|
139
|
+
+ (CGFloat)heightOf:(id)value
|
|
140
|
+
maximum:(CGFloat)maximum
|
|
141
|
+
ofSheet:(UISheetPresentationController *)sheet {
|
|
142
|
+
if ([value isEqual:@"medium"]) {
|
|
143
|
+
return maximum / 2;
|
|
144
|
+
}
|
|
145
|
+
if ([value isKindOfClass:NSNumber.class]) {
|
|
146
|
+
return MIN([value doubleValue], maximum);
|
|
147
|
+
}
|
|
148
|
+
if ([value isEqual:ANNContentDetent]) {
|
|
149
|
+
CGFloat height = [self contentHeightOf:sheet.presentedViewController];
|
|
150
|
+
return height > 0 ? MIN(height, maximum) : maximum;
|
|
151
|
+
}
|
|
152
|
+
return maximum;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// About the largest height of a sheet: its container, or the window before it is shown, below the top safe area.
|
|
156
|
+
+ (CGFloat)maximumDetentHeightOf:(UISheetPresentationController *)sheet {
|
|
157
|
+
UIView *view = sheet.containerView ?: ANNUtils.mainWindow;
|
|
158
|
+
if (!view) {
|
|
159
|
+
return ANNUtils.mainScreen.bounds.size.height;
|
|
160
|
+
}
|
|
161
|
+
return view.bounds.size.height - view.safeAreaInsets.top;
|
|
162
|
+
}
|
|
163
|
+
|
|
84
164
|
+ (UISheetPresentationControllerDetent *)detentFor:(id)value
|
|
85
165
|
ofSheet:(UISheetPresentationController *)sheet {
|
|
86
166
|
if ([value isEqual:@"medium"]) {
|
|
@@ -180,6 +260,7 @@ static NSString *const ANNContentDetent = @"content";
|
|
|
180
260
|
}
|
|
181
261
|
height = newHeight;
|
|
182
262
|
[strongSheet animateChanges:^{
|
|
263
|
+
[self sortDetentsOfSheet:strongSheet];
|
|
183
264
|
[strongSheet invalidateDetents];
|
|
184
265
|
}];
|
|
185
266
|
}
|
|
@@ -201,6 +282,7 @@ static NSString *const ANNContentDetent = @"content";
|
|
|
201
282
|
// The new screen's content mounts may come later: its mounts resolve the detents again too.
|
|
202
283
|
[self followContentOfSheet:sheet when:YES];
|
|
203
284
|
[sheet animateChanges:^{
|
|
285
|
+
[self sortDetentsOfSheet:sheet];
|
|
204
286
|
[sheet invalidateDetents];
|
|
205
287
|
}];
|
|
206
288
|
}
|
|
@@ -179,7 +179,7 @@ static NSMutableArray<ANNOverlay *> *ANNOverlays;
|
|
|
179
179
|
limit:ANNOverlayRenderLimit
|
|
180
180
|
bar:ANNRenderWaitBarWithContent
|
|
181
181
|
barLimits:withContent];
|
|
182
|
-
wait.
|
|
182
|
+
wait.unseenLimit = ANNOverlayRenderLimit;
|
|
183
183
|
wait.protect = ^(dispatch_block_t step) {
|
|
184
184
|
[ANNOverlayCoordinator protectWaitOf:weakOverlay step:step];
|
|
185
185
|
};
|
|
@@ -238,13 +238,7 @@ static NSMutableArray<ANNOverlay *> *ANNOverlays;
|
|
|
238
238
|
[self dismiss:shown answer:nil];
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
|
-
|
|
242
|
-
UIWindowScene *scene = mainWindow.windowScene;
|
|
243
|
-
// `initWithFrame:` is deprecated from iOS 26 on and warns only with a deployment target from 26: a window
|
|
244
|
-
// without a scene is made so, and joins the scene as the main window gets it.
|
|
245
|
-
ANNOverlayWindow *window =
|
|
246
|
-
scene ? [[ANNOverlayWindow alloc] initWithWindowScene:scene]
|
|
247
|
-
: [[ANNOverlayWindow alloc] initWithFrame:ANNUtils.mainScreen.bounds];
|
|
241
|
+
ANNOverlayWindow *window = [ANNUtils makeWindowOfClass:ANNOverlayWindow.class];
|
|
248
242
|
window.windowLevel = UIWindowLevelNormal;
|
|
249
243
|
window.backgroundColor = UIColor.clearColor;
|
|
250
244
|
window.previousWindow = [self keyWindow];
|
|
@@ -69,7 +69,10 @@ typedef NS_ENUM(NSInteger, ANNRootShowState) {
|
|
|
69
69
|
// The nodes whose appearance the transition reports itself (`driveAppearanceOf:`), while `driving`.
|
|
70
70
|
@property(nonatomic, copy) NSArray<UIViewController *> *driven;
|
|
71
71
|
@property(nonatomic) BOOL driving;
|
|
72
|
+
// The snapshot of the window as it was: it dissolves over the new root (`dissolves`), plays its `exit` (`custom`), or
|
|
73
|
+
// only covers the old root's modals while they go, and leaves as the new root is the window's.
|
|
72
74
|
@property(nonatomic, strong, nullable) UIView *snapshot;
|
|
75
|
+
@property(nonatomic) BOOL dissolves;
|
|
73
76
|
// The root is the window's root: the old root's modals went before it (`startTransitionOf:done:`).
|
|
74
77
|
@property(nonatomic) BOOL installed;
|
|
75
78
|
// The root's view waits in the window under the current root (`park:`).
|
|
@@ -80,6 +83,10 @@ typedef NS_ENUM(NSInteger, ANNRootShowState) {
|
|
|
80
83
|
@property(nonatomic, strong, nullable) ANNFrameDriver *driver;
|
|
81
84
|
@property(nonatomic, copy, nullable) NSArray<ANNViewTracks *> *tracks;
|
|
82
85
|
@property(nonatomic) BOOL animating;
|
|
86
|
+
// The new root's view takes no touches while it animates, and whether it took them before: Core Animation draws it
|
|
87
|
+
// elsewhere than where it is (the view itself stays in place), so a tap on the old screen would reach it.
|
|
88
|
+
@property(nonatomic, weak, nullable) UIView *untouchableRoot;
|
|
89
|
+
@property(nonatomic) BOOL rootTouchesBefore;
|
|
83
90
|
@property(nonatomic) BOOL layersShown;
|
|
84
91
|
@end
|
|
85
92
|
|
|
@@ -293,7 +300,7 @@ static __weak ANNRootShow *ANNAnimatingShow;
|
|
|
293
300
|
barLimits:contentFirst ? ownPhase : withContent];
|
|
294
301
|
// A screen the user won't see at once (an unselected tab's) never holds the root longer than the limit, also with
|
|
295
302
|
// `waitForRender: true`.
|
|
296
|
-
wait.
|
|
303
|
+
wait.unseenLimit = ANNRootRenderLimit;
|
|
297
304
|
wait.protect = ^(dispatch_block_t step) {
|
|
298
305
|
[ANNRootCoordinator protect:weakShow step:step];
|
|
299
306
|
};
|
|
@@ -415,9 +422,14 @@ static __weak ANNRootShow *ANNAnimatingShow;
|
|
|
415
422
|
BOOL seen = !window.hidden && scene != nil &&
|
|
416
423
|
scene.activationState != UISceneActivationStateBackground;
|
|
417
424
|
BOOL dissolves = !overSplash && !enterDisabled && !custom && seen;
|
|
425
|
+
show.dissolves = dissolves;
|
|
418
426
|
show.custom = custom && seen;
|
|
419
|
-
|
|
420
|
-
|
|
427
|
+
// UIKit draws the dismissal of the old root's modals, without animation too (a sheet's dim goes a frame before
|
|
428
|
+
// its card): with nothing to dissolve, the snapshot covers them until the new root is in place.
|
|
429
|
+
BOOL covers = seen && old.presentedViewController != nil;
|
|
430
|
+
UIView *snapshot = dissolves || show.custom || covers
|
|
431
|
+
? [window snapshotViewAfterScreenUpdates:NO]
|
|
432
|
+
: nil;
|
|
421
433
|
|
|
422
434
|
show.state = ANNRootShowStateTransition;
|
|
423
435
|
// It shows from here: a stack in it counts as on screen.
|
|
@@ -480,7 +492,8 @@ static __weak ANNRootShow *ANNAnimatingShow;
|
|
|
480
492
|
[self endTransitionOf:show];
|
|
481
493
|
return;
|
|
482
494
|
}
|
|
483
|
-
|
|
495
|
+
// A snapshot that only covered the old root's modals leaves in this turn, with the new root in place under it.
|
|
496
|
+
if (!snapshot || !show.dissolves) {
|
|
484
497
|
[self endTransitionOf:show];
|
|
485
498
|
return;
|
|
486
499
|
}
|
|
@@ -524,20 +537,43 @@ static __weak ANNRootShow *ANNAnimatingShow;
|
|
|
524
537
|
NSMutableArray<ANNViewTracks *> *tracks = [NSMutableArray new];
|
|
525
538
|
ANNViewAnimationOptions *enter = [ANNAnimationRules playingSide:animation.enter];
|
|
526
539
|
ANNViewAnimationOptions *exit = [ANNAnimationRules playingSide:animation.exit];
|
|
527
|
-
if (enter && rootView) {
|
|
528
|
-
[tracks addObject:[[ANNViewTracks alloc] initWithView:rootView
|
|
529
|
-
side:enter
|
|
530
|
-
alphaBefore:rootView.alpha]];
|
|
531
|
-
}
|
|
532
|
-
if (exit && snapshot) {
|
|
533
|
-
[tracks addObject:[[ANNViewTracks alloc] initWithView:snapshot
|
|
534
|
-
side:exit
|
|
535
|
-
alphaBefore:snapshot.alpha]];
|
|
536
|
-
}
|
|
537
540
|
NSTimeInterval length =
|
|
538
541
|
MAX([ANNAnimationRules lengthOfSide:enter], [ANNAnimationRules lengthOfSide:exit]);
|
|
542
|
+
if (UIAccessibilityIsReduceMotionEnabled() && length > 0) {
|
|
543
|
+
// With the system's Reduce Motion on, nothing moves: the new root fades in over the snapshot in the same
|
|
544
|
+
// length, or the snapshot fades out without a new root's view.
|
|
545
|
+
if (rootView) {
|
|
546
|
+
[tracks addObject:[[ANNViewTracks alloc] initWithView:rootView
|
|
547
|
+
fadeFrom:0
|
|
548
|
+
to:rootView.alpha
|
|
549
|
+
duration:length
|
|
550
|
+
alphaBefore:rootView.alpha]];
|
|
551
|
+
} else if (snapshot) {
|
|
552
|
+
[tracks addObject:[[ANNViewTracks alloc] initWithView:snapshot
|
|
553
|
+
fadeFrom:snapshot.alpha
|
|
554
|
+
to:0
|
|
555
|
+
duration:length
|
|
556
|
+
alphaBefore:snapshot.alpha]];
|
|
557
|
+
}
|
|
558
|
+
} else {
|
|
559
|
+
if (enter && rootView) {
|
|
560
|
+
[tracks addObject:[[ANNViewTracks alloc] initWithView:rootView
|
|
561
|
+
side:enter
|
|
562
|
+
alphaBefore:rootView.alpha]];
|
|
563
|
+
}
|
|
564
|
+
if (exit && snapshot) {
|
|
565
|
+
[tracks addObject:[[ANNViewTracks alloc] initWithView:snapshot
|
|
566
|
+
side:exit
|
|
567
|
+
alphaBefore:snapshot.alpha]];
|
|
568
|
+
}
|
|
569
|
+
}
|
|
539
570
|
show.tracks = tracks;
|
|
540
571
|
show.animating = YES;
|
|
572
|
+
if (rootView) {
|
|
573
|
+
show.untouchableRoot = rootView;
|
|
574
|
+
show.rootTouchesBefore = rootView.userInteractionEnabled;
|
|
575
|
+
rootView.userInteractionEnabled = NO;
|
|
576
|
+
}
|
|
541
577
|
ANNAnimatingShow = show;
|
|
542
578
|
show.driver = [[ANNFrameDriver alloc] initWithClients:tracks length:length];
|
|
543
579
|
// The layers' state from here on: the chain may start and a newer `setRoot` stops it.
|
|
@@ -574,8 +610,8 @@ static __weak ANNRootShow *ANNAnimatingShow;
|
|
|
574
610
|
[self finishLayersOf:show];
|
|
575
611
|
}
|
|
576
612
|
|
|
577
|
-
// The animation stops
|
|
578
|
-
// had and the snapshot goes.
|
|
613
|
+
// The animation stops (its end, a newer `setRoot`, a reload, a failure): its animations go, the views get back what
|
|
614
|
+
// they had and the snapshot goes.
|
|
579
615
|
+ (void)stopAnimationOf:(ANNRootShow *)show {
|
|
580
616
|
if (!show.animating) {
|
|
581
617
|
return;
|
|
@@ -583,13 +619,16 @@ static __weak ANNRootShow *ANNAnimatingShow;
|
|
|
583
619
|
show.animating = NO;
|
|
584
620
|
[show.driver cancel];
|
|
585
621
|
show.driver = nil;
|
|
622
|
+
show.untouchableRoot.userInteractionEnabled = show.rootTouchesBefore;
|
|
623
|
+
show.untouchableRoot = nil;
|
|
586
624
|
for (ANNViewTracks *tracks in show.tracks) {
|
|
587
625
|
[tracks restore];
|
|
588
626
|
}
|
|
589
627
|
show.tracks = nil;
|
|
590
|
-
// UIKit works out the safe area of the window's root view from where the view is
|
|
591
|
-
//
|
|
592
|
-
//
|
|
628
|
+
// UIKit works out the safe area of the window's root view from where the view is: moved away from the top edge by
|
|
629
|
+
// a transform it has no top inset, and putting the transform back doesn't make UIKit work it out again. `enter`
|
|
630
|
+
// moves only what Core Animation draws now; the layout stays, so the root, its bars and its screens end with the
|
|
631
|
+
// window's safe area whatever moved them.
|
|
593
632
|
UIView *rootView = show.root.viewIfLoaded;
|
|
594
633
|
[rootView setNeedsLayout];
|
|
595
634
|
[rootView layoutIfNeeded];
|
|
@@ -7,9 +7,11 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
7
7
|
/// either at once. The status bar follows the Info.plist keys `UIStatusBarStyle` and `UIStatusBarHidden`. Main queue.
|
|
8
8
|
@interface ANNSplashViewController : UIViewController
|
|
9
9
|
|
|
10
|
-
/// The copy of the launch screen
|
|
11
|
-
///
|
|
12
|
-
///
|
|
10
|
+
/// The copy of the launch screen. When iOS builds it from the Info.plist (`UILaunchScreen`, or the default of
|
|
11
|
+
/// `UILaunchScreens`), the same color, image and bars as plain views; else the initial view controller of
|
|
12
|
+
/// `UILaunchStoryboardName` as a child (a storyboard that doesn't load: the first view of the nib of that name), else
|
|
13
|
+
/// the legacy launch images, full screen. Nil when the app has none of these: the window then has no root view
|
|
14
|
+
/// controller until the first root.
|
|
13
15
|
+ (nullable instancetype)launchScreenCopyWithBounds:(CGRect)bounds;
|
|
14
16
|
|
|
15
17
|
/// The blank screen after a reload: clear when the default options give the window a color (`window.backgroundColor`),
|
|
@@ -34,9 +34,63 @@ static NSArray<NSString *> *ANNLegacyLaunchImageNames(CGFloat height) {
|
|
|
34
34
|
return names;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
static NSDictionary *ANNDictionaryOrNil(id value) {
|
|
38
|
+
return [value isKindOfClass:NSDictionary.class] ? value : nil;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static NSString *ANNStringOrNil(id value) {
|
|
42
|
+
return [value isKindOfClass:NSString.class] && [value length] > 0 ? value : nil;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// The definition that a plural key (`UILaunchScreens`, `UILaunchStoryboards`) marks as its default.
|
|
46
|
+
static NSDictionary *ANNDefaultDefinition(id plural, NSString *definitionsKey,
|
|
47
|
+
NSString *identifierKey, NSString *defaultKey) {
|
|
48
|
+
NSDictionary *dictionary = ANNDictionaryOrNil(plural);
|
|
49
|
+
NSArray *definitions = dictionary[definitionsKey];
|
|
50
|
+
NSString *defaultIdentifier = ANNStringOrNil(dictionary[defaultKey]);
|
|
51
|
+
if (![definitions isKindOfClass:NSArray.class] || !defaultIdentifier) {
|
|
52
|
+
return nil;
|
|
53
|
+
}
|
|
54
|
+
for (id definition in definitions) {
|
|
55
|
+
NSDictionary *entry = ANNDictionaryOrNil(definition);
|
|
56
|
+
if ([entry[identifierKey] isEqual:defaultIdentifier]) {
|
|
57
|
+
return entry;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return nil;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// The launch screen that iOS builds from the Info.plist without a storyboard, or nil when it shows a storyboard. Of
|
|
64
|
+
// `UILaunchStoryboardName`, `UILaunchScreen`, the default of `UILaunchStoryboards` and the default of
|
|
65
|
+
// `UILaunchScreens`, the last one present wins (SplashBoard's `XBApplicationLaunchCompatibilityInfo`). A launch by a
|
|
66
|
+
// link that `UILaunchScreens` maps to a screen of its own still gets the default here.
|
|
67
|
+
static NSDictionary *ANNLaunchScreenConfiguration(NSBundle *bundle) {
|
|
68
|
+
NSDictionary *screen =
|
|
69
|
+
ANNDefaultDefinition([bundle objectForInfoDictionaryKey:@"UILaunchScreens"],
|
|
70
|
+
@"UILaunchScreenDefinitions", @"UILaunchScreenIdentifier",
|
|
71
|
+
@"UIDefaultLaunchScreen");
|
|
72
|
+
if (screen) {
|
|
73
|
+
return screen;
|
|
74
|
+
}
|
|
75
|
+
if (ANNDefaultDefinition([bundle objectForInfoDictionaryKey:@"UILaunchStoryboards"],
|
|
76
|
+
@"UILaunchStoryboardDefinitions", @"UILaunchStoryboardIdentifier",
|
|
77
|
+
@"UIDefaultLaunchStoryboard")) {
|
|
78
|
+
return nil;
|
|
79
|
+
}
|
|
80
|
+
return ANNDictionaryOrNil([bundle objectForInfoDictionaryKey:@"UILaunchScreen"]);
|
|
81
|
+
}
|
|
82
|
+
|
|
37
83
|
@implementation ANNSplashViewController {
|
|
38
84
|
UIViewController *_content;
|
|
39
85
|
UIView *_contentView;
|
|
86
|
+
NSDictionary *_launchScreen;
|
|
87
|
+
// The parts of a launch screen built from `UILaunchScreen`, laid out once the safe area is known.
|
|
88
|
+
UIImageView *_imageView;
|
|
89
|
+
BOOL _imageRespectsSafeArea;
|
|
90
|
+
UINavigationBar *_navigationBar;
|
|
91
|
+
UIImageView *_navigationBarImageView;
|
|
92
|
+
UIView *_bottomBar;
|
|
93
|
+
UIImageView *_bottomBarImageView;
|
|
40
94
|
}
|
|
41
95
|
|
|
42
96
|
- (instancetype)initWithContent:(UIViewController *)content
|
|
@@ -52,6 +106,12 @@ static NSArray<NSString *> *ANNLegacyLaunchImageNames(CGFloat height) {
|
|
|
52
106
|
|
|
53
107
|
+ (instancetype)launchScreenCopyWithBounds:(CGRect)bounds {
|
|
54
108
|
NSBundle *bundle = NSBundle.mainBundle;
|
|
109
|
+
NSDictionary *launchScreen = ANNLaunchScreenConfiguration(bundle);
|
|
110
|
+
if (launchScreen) {
|
|
111
|
+
ANNSplashViewController *copy = [[self alloc] initWithContent:nil contentView:nil blank:NO];
|
|
112
|
+
copy->_launchScreen = launchScreen;
|
|
113
|
+
return copy;
|
|
114
|
+
}
|
|
55
115
|
NSString *storyboardName = [bundle objectForInfoDictionaryKey:@"UILaunchStoryboardName"];
|
|
56
116
|
if ([storyboardName isKindOfClass:NSString.class] && storyboardName.length > 0) {
|
|
57
117
|
UIViewController *initial = nil;
|
|
@@ -97,6 +157,10 @@ static NSArray<NSString *> *ANNLegacyLaunchImageNames(CGFloat height) {
|
|
|
97
157
|
view.backgroundColor = windowHasColor ? UIColor.clearColor : UIColor.systemBackgroundColor;
|
|
98
158
|
return;
|
|
99
159
|
}
|
|
160
|
+
if (_launchScreen) {
|
|
161
|
+
[self buildLaunchScreen];
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
100
164
|
UIView *contentView = _contentView;
|
|
101
165
|
if (_content) {
|
|
102
166
|
[self addChildViewController:_content];
|
|
@@ -109,6 +173,89 @@ static NSArray<NSString *> *ANNLegacyLaunchImageNames(CGFloat height) {
|
|
|
109
173
|
[_content didMoveToParentViewController:self];
|
|
110
174
|
}
|
|
111
175
|
|
|
176
|
+
#pragma mark - The launch screen of `UILaunchScreen`
|
|
177
|
+
|
|
178
|
+
// Built as SplashBoard builds it: the named color over the whole screen, else the system background; the named image
|
|
179
|
+
// at its own size in the middle of the screen or of its safe area, stretched instead when the asset has slicing; a tab
|
|
180
|
+
// bar or a toolbar at the bottom and a navigation bar at the top, the system's own bars, or the bar's named image
|
|
181
|
+
// stretched over the bar's place. A name the asset catalog doesn't have leaves its part out, as iOS does.
|
|
182
|
+
- (void)buildLaunchScreen {
|
|
183
|
+
UIView *view = self.view;
|
|
184
|
+
NSString *colorName = ANNStringOrNil(_launchScreen[@"UIColorName"]);
|
|
185
|
+
UIColor *color = colorName ? [UIColor colorNamed:colorName] : nil;
|
|
186
|
+
view.backgroundColor = color ?: UIColor.systemBackgroundColor;
|
|
187
|
+
|
|
188
|
+
NSString *imageName = ANNStringOrNil(_launchScreen[@"UIImageName"]);
|
|
189
|
+
UIImage *image = imageName ? [UIImage imageNamed:imageName] : nil;
|
|
190
|
+
if (image) {
|
|
191
|
+
_imageView = [[UIImageView alloc] initWithImage:image];
|
|
192
|
+
_imageView.contentMode = UIEdgeInsetsEqualToEdgeInsets(image.capInsets, UIEdgeInsetsZero)
|
|
193
|
+
? UIViewContentModeCenter
|
|
194
|
+
: UIViewContentModeScaleToFill;
|
|
195
|
+
id respects = _launchScreen[@"UIImageRespectsSafeAreaInsets"];
|
|
196
|
+
_imageRespectsSafeArea = [respects respondsToSelector:@selector(boolValue)] &&
|
|
197
|
+
[respects boolValue];
|
|
198
|
+
[view addSubview:_imageView];
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// A toolbar takes the bottom before a tab bar; a navigation bar comes on top of either.
|
|
202
|
+
id toolbar = _launchScreen[@"UIToolbar"];
|
|
203
|
+
id tabBar = _launchScreen[@"UITabBar"];
|
|
204
|
+
if (toolbar || tabBar) {
|
|
205
|
+
_bottomBar = toolbar ? [UIToolbar new] : [UITabBar new];
|
|
206
|
+
_bottomBarImageView = [self addBar:_bottomBar configuration:toolbar ?: tabBar];
|
|
207
|
+
}
|
|
208
|
+
id navigationBar = _launchScreen[@"UINavigationBar"];
|
|
209
|
+
if (navigationBar) {
|
|
210
|
+
_navigationBar = [UINavigationBar new];
|
|
211
|
+
_navigationBarImageView = [self addBar:_navigationBar configuration:navigationBar];
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Adds the bar, or its image in its place when its configuration names one that loads.
|
|
216
|
+
- (UIImageView *)addBar:(UIView *)bar configuration:(id)configuration {
|
|
217
|
+
NSString *name = ANNStringOrNil(ANNDictionaryOrNil(configuration)[@"UIImageName"]);
|
|
218
|
+
UIImage *image = name ? [UIImage imageNamed:name] : nil;
|
|
219
|
+
UIImageView *imageView = image ? [[UIImageView alloc] initWithImage:image] : nil;
|
|
220
|
+
bar.hidden = imageView != nil;
|
|
221
|
+
[self.view addSubview:bar];
|
|
222
|
+
if (imageView) {
|
|
223
|
+
[self.view addSubview:imageView];
|
|
224
|
+
}
|
|
225
|
+
return imageView;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// The safe area is known only in the window, so the parts are laid out here, after every change of it.
|
|
229
|
+
- (void)viewDidLayoutSubviews {
|
|
230
|
+
[super viewDidLayoutSubviews];
|
|
231
|
+
if (!_launchScreen) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
CGRect bounds = self.view.bounds;
|
|
235
|
+
UIEdgeInsets safeArea = self.view.safeAreaInsets;
|
|
236
|
+
_imageView.frame =
|
|
237
|
+
_imageRespectsSafeArea ? UIEdgeInsetsInsetRect(bounds, safeArea) : bounds;
|
|
238
|
+
[self layOutBar:_bottomBar imageView:_bottomBarImageView atBottom:YES];
|
|
239
|
+
[self layOutBar:_navigationBar imageView:_navigationBarImageView atBottom:NO];
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// A bar is as tall as UIKit makes it, plus the safe area on its edge of the screen, and as wide as the screen.
|
|
243
|
+
- (void)layOutBar:(UIView *)bar
|
|
244
|
+
imageView:(UIImageView *)imageView
|
|
245
|
+
atBottom:(BOOL)atBottom {
|
|
246
|
+
if (!bar) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
CGRect bounds = self.view.bounds;
|
|
250
|
+
UIEdgeInsets safeArea = self.view.safeAreaInsets;
|
|
251
|
+
CGFloat height = [bar sizeThatFits:bounds.size].height +
|
|
252
|
+
(atBottom ? safeArea.bottom : safeArea.top);
|
|
253
|
+
CGFloat y = atBottom ? CGRectGetMaxY(bounds) - height : CGRectGetMinY(bounds);
|
|
254
|
+
CGRect frame = CGRectMake(CGRectGetMinX(bounds), y, CGRectGetWidth(bounds), height);
|
|
255
|
+
bar.frame = frame;
|
|
256
|
+
imageView.frame = frame;
|
|
257
|
+
}
|
|
258
|
+
|
|
112
259
|
#pragma mark - The status bar, as the launch screen had it
|
|
113
260
|
|
|
114
261
|
- (UIStatusBarStyle)preferredStatusBarStyle {
|
|
@@ -19,11 +19,19 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
19
19
|
/// it. Nothing before the screen's view is loaded.
|
|
20
20
|
- (void)applyBackground:(ANNNavigationOptions *)resolvedOptions;
|
|
21
21
|
|
|
22
|
-
/// `statusBar.blur` (iOS): UIKit's regular blur over the screen's own view in the frame of the scene's status bar
|
|
23
|
-
///
|
|
24
|
-
///
|
|
22
|
+
/// `statusBar.blur` (iOS): UIKit's regular blur over the screen's own view in the frame of the scene's status bar (x 0,
|
|
23
|
+
/// the view's width), laid out at once; `false` or none removes it. At each appearance and at a merge that names it;
|
|
24
|
+
/// nothing before the screen's view is loaded.
|
|
25
25
|
- (void)applyStatusBarBlur:(ANNNavigationOptions *)resolvedOptions;
|
|
26
26
|
|
|
27
|
+
/// The blur takes the status bar's frame as it is now; nothing without a blur. The single place of its frame: the blur
|
|
28
|
+
/// as it is applied, the screen's view laid out (a rotation, a new window size, a new safe area), a size transition
|
|
29
|
+
/// along its animation and at its end, the turn after new traits, and `statusBarDidChange`.
|
|
30
|
+
- (void)layOutStatusBarBlur;
|
|
31
|
+
|
|
32
|
+
/// The status bar was asked again (hidden or shown, a new style): every blur takes its frame.
|
|
33
|
+
+ (void)statusBarDidChange;
|
|
34
|
+
|
|
27
35
|
/// The blur stays the last subview of the screen's view: the content added after it goes under it.
|
|
28
36
|
- (void)keepStatusBarBlurOnTop;
|
|
29
37
|
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
#import "ANNTopBarPresenter.h"
|
|
6
6
|
#import "ANNUtils.h"
|
|
7
7
|
|
|
8
|
+
// The presenters whose screen shows `statusBar.blur`: the status bar hidden or shown lays out no view, so they hear of
|
|
9
|
+
// it from the system UI (`statusBarDidChange`).
|
|
10
|
+
static NSHashTable<ANNComponentPresenter *> *ANNBlurringPresenters;
|
|
11
|
+
|
|
8
12
|
@implementation ANNComponentPresenter {
|
|
9
13
|
// `statusBar.blur` while it is on.
|
|
10
14
|
UIVisualEffectView *_statusBarBlur;
|
|
@@ -95,9 +99,7 @@
|
|
|
95
99
|
|
|
96
100
|
#pragma mark - The status bar's blur (`statusBar.blur`)
|
|
97
101
|
|
|
98
|
-
// Over the screen's own view, never over a React view; no touches, nothing for VoiceOver.
|
|
99
|
-
// status bar's as it is now, in the view's own coordinates without a conversion: a pushed screen's view may still be
|
|
100
|
-
// out of place while it appears.
|
|
102
|
+
// Over the screen's own view, never over a React view; no touches, nothing for VoiceOver.
|
|
101
103
|
- (void)applyStatusBarBlur:(ANNNavigationOptions *)resolvedOptions {
|
|
102
104
|
ANNComponentViewController *screen = self.screen;
|
|
103
105
|
if (!screen.isViewLoaded) {
|
|
@@ -106,6 +108,7 @@
|
|
|
106
108
|
if (![resolvedOptions.statusBar.blur withDefault:NO]) {
|
|
107
109
|
[_statusBarBlur removeFromSuperview];
|
|
108
110
|
_statusBarBlur = nil;
|
|
111
|
+
[ANNBlurringPresenters removeObject:self];
|
|
109
112
|
return;
|
|
110
113
|
}
|
|
111
114
|
UIView *view = screen.view;
|
|
@@ -115,15 +118,40 @@
|
|
|
115
118
|
_statusBarBlur.userInteractionEnabled = NO;
|
|
116
119
|
_statusBarBlur.isAccessibilityElement = NO;
|
|
117
120
|
_statusBarBlur.accessibilityElementsHidden = YES;
|
|
121
|
+
if (!ANNBlurringPresenters) {
|
|
122
|
+
ANNBlurringPresenters = [NSHashTable weakObjectsHashTable];
|
|
123
|
+
}
|
|
124
|
+
[ANNBlurringPresenters addObject:self];
|
|
118
125
|
}
|
|
119
|
-
CGRect statusBar = ANNUtils.statusBarFrame;
|
|
120
|
-
_statusBarBlur.frame = CGRectMake(0, CGRectGetMinY(statusBar), CGRectGetWidth(view.bounds),
|
|
121
|
-
CGRectGetHeight(statusBar));
|
|
122
126
|
if (_statusBarBlur.superview != view) {
|
|
123
127
|
[view addSubview:_statusBarBlur];
|
|
124
128
|
} else {
|
|
125
129
|
[view bringSubviewToFront:_statusBarBlur];
|
|
126
130
|
}
|
|
131
|
+
[self layOutStatusBarBlur];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// The status bar's frame in the scene of the screen's window (the main window's before the screen is in one), in the
|
|
135
|
+
// view's own coordinates without a conversion: a pushed screen's view may still be out of place while it appears. A
|
|
136
|
+
// hidden status bar has no frame, and the blur no height.
|
|
137
|
+
- (void)layOutStatusBarBlur {
|
|
138
|
+
UIView *view = _statusBarBlur.superview;
|
|
139
|
+
if (!view) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
UIWindowScene *scene = view.window.windowScene;
|
|
143
|
+
CGRect statusBar = scene ? scene.statusBarManager.statusBarFrame : ANNUtils.statusBarFrame;
|
|
144
|
+
CGRect frame = CGRectMake(0, CGRectGetMinY(statusBar), CGRectGetWidth(view.bounds),
|
|
145
|
+
CGRectGetHeight(statusBar));
|
|
146
|
+
if (!CGRectEqualToRect(_statusBarBlur.frame, frame)) {
|
|
147
|
+
_statusBarBlur.frame = frame;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
+ (void)statusBarDidChange {
|
|
152
|
+
for (ANNComponentPresenter *presenter in ANNBlurringPresenters.allObjects) {
|
|
153
|
+
[presenter layOutStatusBarBlur];
|
|
154
|
+
}
|
|
127
155
|
}
|
|
128
156
|
|
|
129
157
|
- (void)keepStatusBarBlurOnTop {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#import "ANNArrangementScreenDelegate.h"
|
|
2
2
|
#import "ANNLayoutProtocol.h"
|
|
3
3
|
#import "ANNScreenAppearance.h"
|
|
4
|
+
#import "ANNScreenPlace.h"
|
|
4
5
|
#import "UIViewController+LayoutProtocol.h"
|
|
5
6
|
#import <UIKit/UIKit.h>
|
|
6
7
|
|
|
@@ -10,8 +11,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
10
11
|
///
|
|
11
12
|
/// Its view has the size of the screen of the navigation window's scene; the content sits in the root frame, by the one
|
|
12
13
|
/// "under bars" rule (`ANNScreenBars`). Every recompute of the frame (a layout, a change of the safe area or the
|
|
13
|
-
/// traits, `mergeOptions`, an appearance) gives the
|
|
14
|
-
/// (`
|
|
14
|
+
/// traits, `mergeOptions`, an appearance) gives the store the screen's insets, padding and regions
|
|
15
|
+
/// (`ANNScreenEnvironment`). Its presenter is an `ANNComponentPresenter`.
|
|
15
16
|
///
|
|
16
17
|
/// The screen answers UIKit's questions about the system UI (native screens too): the status bar's style and visibility
|
|
17
18
|
/// (never animated), the orientations, the home indicator, the deferred edges and the vertical bars, from its resolved
|
|
@@ -42,21 +43,22 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
42
43
|
/// nobody rendered gets its content when UIKit first loads its view.
|
|
43
44
|
- (void)render;
|
|
44
45
|
|
|
46
|
+
/// Where the screen will show while it waits for its content out of it (parked by a stack's or `showInColumn`'s wait,
|
|
47
|
+
/// or in a tab rendered before it shows, `ANNParking`): it lays out with that place's safe area and bars
|
|
48
|
+
/// (`ANNScreenPlace`), as it will once it shows there. Asked at each layout, and kept past the parking until UIKit
|
|
49
|
+
/// gives the screen a safe area of its own in a parent (the push lays it out once before that, with none), or as it
|
|
50
|
+
/// appears. Nil: its view's own. Set by the one that parks the screen.
|
|
51
|
+
@property(nonatomic, copy, nullable) ANNScreenPlace *_Nullable (^placeWhileParked)(void);
|
|
52
|
+
|
|
53
|
+
/// The place is kept until the screen appears, not only until UIKit gives it a safe area: a tab's screen rendered
|
|
54
|
+
/// before the tab shows gets a part of it first (the bar without the status bar) as UIKit lays the tab out. Set with
|
|
55
|
+
/// `placeWhileParked`, and goes with it.
|
|
56
|
+
@property(nonatomic) BOOL placeKeptUntilAppearance;
|
|
57
|
+
|
|
45
58
|
/// Applies the "under bars" rule to the root frame again, then gives the modules the insets, the padding and the
|
|
46
59
|
/// regions of the screen. Nothing before the view loaded; the safe area only in a window.
|
|
47
60
|
- (void)updateRootLayout;
|
|
48
61
|
|
|
49
|
-
/// The content view (only the core's React view, never the screen's own view) mounts unseen in `host` (the tabs'
|
|
50
|
-
/// preload window) at the frame it has, while the screen's tab isn't shown. NO when there is nothing to lend: no React
|
|
51
|
-
/// view of its own, in a window already, lent already, or the screen went.
|
|
52
|
-
- (BOOL)lendContentTo:(UIView *)host;
|
|
53
|
-
|
|
54
|
-
/// The lent content comes back into the screen's view at its root frame; also as the screen first appears.
|
|
55
|
-
- (void)takeContentBack;
|
|
56
|
-
|
|
57
|
-
/// The content is lent (`lendContentTo:`): `updateRootLayout` leaves its frame alone meanwhile.
|
|
58
|
-
@property(nonatomic, readonly) BOOL contentIsLent;
|
|
59
|
-
|
|
60
62
|
/// The transition that removes the screen starts (before its destroy): with `blurOnUnmount` in its resolved options,
|
|
61
63
|
/// the editing inside its view ends and the keyboard goes (`blurOnUnmount`).
|
|
62
64
|
- (void)screenWillLeave;
|