@apexnative/navigation 1.0.0-alpha.0 → 1.0.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ApexNavigation.podspec +2 -1
- package/CHANGELOG.md +128 -0
- package/README.md +147 -51
- package/android/CLAUDE.md +78 -25
- package/android/CORE.md +49 -25
- package/android/RECIPES.md +13 -6
- package/android/consumer-rules.pro +6 -0
- package/android/src/main/java/dev/apexnative/navigation/NavigationActivity.kt +85 -10
- package/android/src/main/java/dev/apexnative/navigation/NavigationApplication.kt +34 -13
- package/android/src/main/java/dev/apexnative/navigation/layout/LayoutChecks.kt +5 -1
- package/android/src/main/java/dev/apexnative/navigation/layout/LayoutNode.kt +6 -2
- package/android/src/main/java/dev/apexnative/navigation/nativescreen/NativeScreenContext.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/AnimationsOptions.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/BottomTabOptions.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/BottomTabsOptions.kt +13 -8
- package/android/src/main/java/dev/apexnative/navigation/options/ButtonMenuOptions.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/ButtonOptions.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/options/HardwareBackButtonOptions.kt +9 -1
- package/android/src/main/java/dev/apexnative/navigation/options/LargeTitleOptions.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/LayoutAnimation.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/OptionKey.kt +18 -0
- package/android/src/main/java/dev/apexnative/navigation/options/OptionPaths.kt +91 -0
- package/android/src/main/java/dev/apexnative/navigation/options/OptionsCache.kt +8 -4
- package/android/src/main/java/dev/apexnative/navigation/options/SheetOptions.kt +7 -4
- package/android/src/main/java/dev/apexnative/navigation/options/SideMenuOptions.kt +6 -1
- package/android/src/main/java/dev/apexnative/navigation/options/StackAnimationOptions.kt +40 -2
- package/android/src/main/java/dev/apexnative/navigation/options/StatusBarOptions.kt +7 -3
- package/android/src/main/java/dev/apexnative/navigation/options/TitleOptions.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/TopBarAppearanceOptions.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/TopBarOptions.kt +16 -7
- package/android/src/main/java/dev/apexnative/navigation/options/UserChoices.kt +159 -0
- package/android/src/main/java/dev/apexnative/navigation/react/CommandAnswer.kt +29 -36
- package/android/src/main/java/dev/apexnative/navigation/react/CommandContract.kt +59 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ContentHeights.kt +95 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ContentMounts.kt +66 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ErrorTexts.kt +75 -60
- package/android/src/main/java/dev/apexnative/navigation/react/Hinge.kt +35 -23
- package/android/src/main/java/dev/apexnative/navigation/react/NavigationTurboModule.kt +12 -7
- package/android/src/main/java/dev/apexnative/navigation/react/OptionsCommands.kt +42 -4
- package/android/src/main/java/dev/apexnative/navigation/react/PendingCalls.kt +48 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ReactView.kt +54 -20
- package/android/src/main/java/dev/apexnative/navigation/react/ReloadCoordinator.kt +7 -6
- package/android/src/main/java/dev/apexnative/navigation/react/ScreenEnvironment.kt +177 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ScreenRegions.kt +19 -50
- package/android/src/main/java/dev/apexnative/navigation/react/ScrollEvents.kt +49 -128
- package/android/src/main/java/dev/apexnative/navigation/react/events/AppearanceDispatcher.kt +50 -81
- package/android/src/main/java/dev/apexnative/navigation/react/events/EventContract.kt +226 -0
- package/android/src/main/java/dev/apexnative/navigation/react/events/EventEmitter.kt +135 -94
- package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationState.kt +154 -0
- package/android/src/main/java/dev/apexnative/navigation/react/events/ScreenAppearance.kt +0 -6
- package/android/src/main/java/dev/apexnative/navigation/safearea/SafeAreaView.kt +12 -10
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotContainers.kt +10 -7
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotScreenView.kt +39 -19
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotView.kt +16 -4
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotViews.kt +40 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/ImageKey.kt +66 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/ImageLoader.kt +7 -89
- package/android/src/main/java/dev/apexnative/navigation/utils/ImageRequests.kt +76 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/MaterialTheme.kt +5 -6
- package/android/src/main/java/dev/apexnative/navigation/utils/OptionImages.kt +262 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/SystemAnimations.kt +36 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/UiUtils.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/utils/ViewController.kt +3 -1
- package/android/src/main/java/dev/apexnative/navigation/utils/ViewExtensions.kt +0 -13
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementController.kt +10 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/SecondaryScreenPresenter.kt +13 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/AppliedTabCalls.kt +49 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsCollapseBehavior.kt +5 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsController.kt +108 -34
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsPresenter.kt +25 -24
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowGeometry.kt +22 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabItems.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabsRoom.kt +0 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentPresenter.kt +28 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentViewController.kt +12 -9
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ContentReadiness.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/RenderWait.kt +27 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenFrame.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenReadiness.kt +103 -56
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenSafeArea.kt +29 -11
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/externalcomponent/ExternalComponentViewController.kt +2 -6
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalAnimations.kt +22 -24
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalCoordinator.kt +109 -21
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalRecord.kt +21 -6
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalSheet.kt +476 -73
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalViews.kt +57 -25
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetBack.kt +42 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetStops.kt +83 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackCheck.kt +50 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackState.kt +49 -14
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/Navigator.kt +71 -12
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/RootCoordinator.kt +37 -11
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/overlay/OverlayCoordinator.kt +10 -8
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/Capabilities.kt +11 -4
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ContainerBackground.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ParentController.kt +6 -6
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuController.kt +42 -9
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuMotion.kt +19 -8
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuPresenter.kt +16 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuRules.kt +43 -4
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitPanes.kt +23 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitViewController.kt +77 -17
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/BackPreview.kt +315 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/PreparedFrame.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackCommands.kt +30 -20
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackController.kt +216 -18
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackDisplay.kt +26 -1
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackQueue.kt +149 -41
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackTransitions.kt +26 -8
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackViews.kt +115 -6
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabMotion.kt +142 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabPresenter.kt +222 -48
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/ScreenSearch.kt +3 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/StackSearchPresenter.kt +30 -34
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarComponents.kt +5 -51
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarRowTransition.kt +3 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/ButtonPlaces.kt +11 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/MenuChecks.kt +13 -56
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarPresenter.kt +219 -54
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarVisibility.kt +9 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ScrollEventListener.kt +6 -9
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ViewController.kt +75 -21
- package/android/src/main/java/dev/apexnative/navigation/views/animations/AnimationLayer.kt +73 -0
- package/android/src/main/java/dev/apexnative/navigation/views/animations/Curves.kt +29 -11
- package/android/src/main/java/dev/apexnative/navigation/views/animations/ValueInterpolation.kt +14 -0
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabs.kt +9 -7
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabsLayout.kt +61 -2
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomBottomTabItemView.kt +0 -5
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomTabRow.kt +72 -10
- package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStep.kt +31 -0
- package/android/src/main/java/dev/apexnative/navigation/views/element/ElementTransitions.kt +143 -135
- package/android/src/main/java/dev/apexnative/navigation/views/element/TargetsWait.kt +13 -5
- package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionLayer.kt +37 -112
- package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionTargets.kt +9 -6
- package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionViews.kt +100 -0
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ElementPictures.kt +112 -4
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/FlightGeometry.kt +346 -36
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMorph.kt +199 -0
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/SharedAnimatorFactory.kt +56 -41
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextMorph.kt +176 -0
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewMorph.kt +108 -0
- package/android/src/main/java/dev/apexnative/navigation/views/sidemenu/SideMenuView.kt +12 -3
- package/android/src/main/java/dev/apexnative/navigation/views/stack/ScreenEdge.kt +45 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/StackLayout.kt +140 -1
- package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/Fab.kt +14 -10
- package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabCopy.kt +85 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabMenu.kt +13 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TitleBar.kt +5 -17
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TopBar.kt +73 -34
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonComponentCell.kt +6 -6
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonView.kt +113 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarMenu.kt +219 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonBar.kt +125 -178
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonMenus.kt +34 -64
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonRow.kt +216 -0
- package/android/src/main/jni/ANNContentHeights.cpp +82 -0
- package/android/src/main/res/drawable/apex_navigation_ic_arrow_right.xml +14 -0
- package/android/src/main/res/layout/apex_navigation_menu_header.xml +19 -0
- package/android/src/main/res/layout/apex_navigation_menu_item.xml +68 -0
- package/android/src/main/res/values/styles.xml +1 -1
- package/android/src/main/res/values-night/styles.xml +1 -1
- package/cli/app.js +1 -1
- package/cli/doctor/checks/app.js +77 -14
- package/cli/doctor/checks/splash.js +4 -22
- package/cli/migrate/native.js +18 -0
- package/cli/project.js +10 -2
- package/cli/setup/index.js +18 -0
- package/cli/setup/source.js +2 -1
- package/cli/setup/steps/appDelegate.js +66 -11
- package/cli/setup/steps/mainApplication.js +134 -19
- package/cli/setup/steps/metro.js +46 -0
- package/cli/setup/steps/sceneDelegate.js +108 -0
- package/cli/splash/index.js +3 -1
- package/cli/upgrade/changelog.js +2 -2
- package/docs-md/architecture/native-screens.md +4 -0
- package/docs-md/architecture/theme-and-context.md +131 -12
- package/docs-md/architecture/transitions.md +58 -12
- package/docs-md/containers/modals.md +8 -4
- package/docs-md/containers/overlays.md +3 -1
- package/docs-md/containers/side-menu.md +19 -2
- package/docs-md/containers/tabs.md +5 -1
- package/docs-md/flows/bottom-sheets.md +4 -2
- package/docs-md/flows/forms-in-a-modal.md +1 -1
- package/docs-md/fundamentals/screens-and-props.md +9 -1
- package/docs-md/fundamentals/starting-the-app.md +1 -1
- package/docs-md/guides/cli.md +4 -3
- package/docs-md/guides/deep-links.md +15 -33
- package/docs-md/help/glossary.md +4 -4
- package/docs-md/help/troubleshooting.md +44 -6
- package/docs-md/index.json +57 -1
- package/docs-md/migration/from-expo-router.md +1 -1
- package/docs-md/migration/from-react-native-navigation.md +9 -3
- package/docs-md/migration/from-react-navigation.md +2 -2
- package/docs-md/screen-ui/back-and-gestures.md +46 -2
- package/docs-md/screen-ui/bar-buttons.md +5 -5
- package/docs-md/screen-ui/search.md +1 -1
- package/docs-md/screen-ui/system-ui.md +17 -12
- package/docs-md/screen-ui/toolbar-and-fab.md +4 -2
- package/docs-md/screen-ui/top-bar.md +8 -4
- package/docs-md/start/installation.md +21 -3
- package/ios/Animations/ANNFrameDriver.h +55 -15
- package/ios/Animations/ANNFrameDriver.mm +216 -60
- package/ios/Animations/ANNTransitionAnimator.h +26 -5
- package/ios/Animations/ANNTransitionAnimator.mm +61 -13
- package/ios/Animations/ANNTransitionPlan.h +2 -2
- package/ios/Animations/ANNTransitionPlan.mm +10 -0
- package/ios/Animations/ANNTransitionWait.mm +6 -7
- package/ios/Animations/Elements/ANNElementFinder.h +57 -0
- package/ios/Animations/Elements/ANNElementFinder.mm +174 -2
- package/ios/Animations/Elements/ANNElementTransition.h +10 -8
- package/ios/Animations/Elements/ANNElementTransition.mm +19 -21
- package/ios/Animations/Elements/ANNSharedElementFlight.h +16 -11
- package/ios/Animations/Elements/ANNSharedElementFlight.mm +308 -69
- package/ios/Animations/Interpolators/ANNInterpolate.h +2 -30
- package/ios/Animations/Interpolators/ANNTransformParts.h +48 -0
- package/ios/Animations/Interpolators/ANNTransformParts.mm +507 -0
- package/ios/Animations/Interpolators/ANNViewTracks.h +9 -6
- package/ios/Animations/Interpolators/ANNViewTracks.mm +100 -30
- package/ios/CLAUDE.md +60 -24
- package/ios/CORE.md +44 -34
- package/ios/Contract/ANNCommandAnswer.h +13 -5
- package/ios/Contract/ANNCommandAnswer.mm +40 -32
- package/ios/Contract/ANNCommandContract.h +15 -0
- package/ios/Contract/ANNCommandContract.mm +78 -0
- package/ios/Contract/ANNCommandRunner.h +10 -9
- package/ios/Contract/ANNCommandRunner.mm +22 -28
- package/ios/Contract/ANNErrorTexts.h +6 -2
- package/ios/Contract/ANNErrorTexts.mm +18 -10
- package/ios/Contract/ANNLayoutNode.h +3 -3
- package/ios/Contract/ANNLayoutReader.h +3 -3
- package/ios/Core/ANNAppDelegate.mm +0 -2
- package/ios/Core/ANNAppearanceDispatcher.h +5 -4
- package/ios/Core/ANNAppearanceDispatcher.mm +12 -1
- package/ios/Core/ANNDeepLinkQueue.h +22 -2
- package/ios/Core/ANNDeepLinkQueue.mm +121 -14
- package/ios/Core/ANNErrorHandler.h +9 -4
- package/ios/Core/ANNErrorHandler.mm +20 -2
- package/ios/Core/ANNEventContract.h +246 -0
- package/ios/Core/ANNEventContract.mm +225 -0
- package/ios/Core/ANNEventEmitter.h +6 -2
- package/ios/Core/ANNEventEmitter.mm +117 -80
- package/ios/Core/ANNHinge.h +6 -0
- package/ios/Core/ANNHinge.mm +15 -4
- package/ios/Core/ANNJavaScriptCalls.h +33 -0
- package/ios/Core/ANNJavaScriptCalls.mm +52 -0
- package/ios/Core/ANNLayoutProtocol.h +5 -5
- package/ios/Core/ANNNavigationState.h +7 -5
- package/ios/Core/ANNNavigationState.mm +8 -7
- package/ios/Core/ANNNodeHelper.h +32 -12
- package/ios/Core/ANNNodeHelper.mm +100 -3
- package/ios/Core/ANNParking.h +5 -4
- package/ios/Core/ANNReloadCoordinator.mm +5 -12
- package/ios/Core/ANNRenderWait.h +20 -6
- package/ios/Core/ANNRenderWait.mm +143 -56
- package/ios/Core/ANNSceneDelegate.mm +25 -15
- package/ios/Core/ANNSystemUI.h +3 -2
- package/ios/Core/ANNSystemUI.mm +7 -0
- package/ios/Core/ANNUtils.h +7 -0
- package/ios/Core/ANNUtils.mm +10 -0
- package/ios/Core/ApexNavigation+Internal.h +1 -1
- package/ios/Core/ApexNavigation.mm +7 -6
- package/ios/Core/UIViewController+LayoutProtocol.h +9 -2
- package/ios/Core/UIViewController+LayoutProtocol.mm +8 -0
- package/ios/Layouts/Arrangement/ANNArrangementState.h +2 -17
- package/ios/Layouts/Arrangement/ANNArrangementState.mm +0 -38
- package/ios/Layouts/Arrangement/ANNArrangementViewController.mm +10 -8
- package/ios/Layouts/Modal/ANNModalCoordinator.h +1 -1
- package/ios/Layouts/Modal/ANNModalCoordinator.mm +57 -16
- package/ios/Layouts/Modal/ANNModalPresentation.h +8 -5
- package/ios/Layouts/Modal/ANNModalPresentation.mm +12 -12
- package/ios/Layouts/Modal/ANNSheetPresenter.mm +83 -1
- package/ios/Layouts/Overlay/ANNOverlayCoordinator.mm +2 -8
- package/ios/Layouts/Root/ANNRootCoordinator.mm +58 -19
- package/ios/Layouts/Root/ANNSplashViewController.h +5 -3
- package/ios/Layouts/Root/ANNSplashViewController.mm +147 -0
- package/ios/Layouts/Screen/ANNComponentPresenter.h +11 -3
- package/ios/Layouts/Screen/ANNComponentPresenter.mm +34 -6
- package/ios/Layouts/Screen/ANNComponentViewController.h +15 -13
- package/ios/Layouts/Screen/ANNComponentViewController.mm +130 -75
- package/ios/Layouts/Screen/ANNNativeScreenContext.mm +7 -5
- package/ios/Layouts/Screen/ANNPreviewInteraction.h +7 -4
- package/ios/Layouts/Screen/ANNPreviewInteraction.mm +72 -10
- package/ios/Layouts/Screen/ANNScreenEnvironment.h +63 -0
- package/ios/Layouts/Screen/ANNScreenEnvironment.mm +181 -0
- package/ios/Layouts/Screen/ANNScreenPlace.h +53 -0
- package/ios/Layouts/Screen/ANNScreenPlace.mm +205 -0
- package/ios/Layouts/Screen/ANNScreenRegions.h +3 -18
- package/ios/Layouts/Screen/ANNScreenRegions.mm +9 -44
- package/ios/Layouts/Screen/ANNScreenSafeArea.h +4 -9
- package/ios/Layouts/Screen/ANNScreenSafeArea.mm +14 -16
- package/ios/Layouts/Screen/ANNScreenSettling.h +32 -0
- package/ios/Layouts/Screen/ANNScreenSettling.mm +137 -0
- package/ios/Layouts/SideMenu/ANNSideMenuTypes.h +8 -0
- package/ios/Layouts/SideMenu/ANNSideMenuViewController.mm +83 -14
- package/ios/Layouts/SplitView/ANNSplitViewCommands.h +3 -2
- package/ios/Layouts/SplitView/ANNSplitViewCommands.mm +105 -39
- package/ios/Layouts/SplitView/ANNSplitViewController.mm +7 -8
- package/ios/Layouts/Stack/ANNPreviewPush.h +7 -6
- package/ios/Layouts/Stack/ANNPreviewPush.mm +142 -27
- package/ios/Layouts/Stack/ANNStackAnimatingDelegate.h +11 -2
- package/ios/Layouts/Stack/ANNStackAnimatingDelegate.mm +14 -7
- package/ios/Layouts/Stack/ANNStackCommands.mm +1 -0
- package/ios/Layouts/Stack/ANNStackController.h +8 -0
- package/ios/Layouts/Stack/ANNStackController.mm +184 -16
- package/ios/Layouts/Stack/ANNStackQueue.h +5 -2
- package/ios/Layouts/Stack/ANNStackQueue.mm +56 -43
- package/ios/Layouts/Stack/ANNSwipePopInteraction.h +26 -0
- package/ios/Layouts/Stack/ANNSwipePopInteraction.mm +185 -0
- package/ios/Layouts/Stack/InteractivePopGestureDelegate.mm +28 -4
- package/ios/Layouts/Stack/UINavigationController+ANNCommands.h +4 -2
- package/ios/Layouts/Stack/UINavigationController+ANNCommands.mm +2 -3
- package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.h +4 -0
- package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.mm +11 -0
- package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.h +12 -1
- package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.mm +23 -0
- package/ios/Layouts/Tabs/ANNBottomTabsController.h +3 -0
- package/ios/Layouts/Tabs/ANNBottomTabsController.mm +237 -57
- package/ios/Layouts/Tabs/ANNBottomTabsCustomRow.mm +8 -3
- package/ios/Layouts/Tabs/ANNBottomTabsPresenter.h +6 -2
- package/ios/Layouts/Tabs/ANNBottomTabsPresenter.mm +232 -43
- package/ios/Layouts/Tabs/ANNTabsDesign.h +6 -5
- package/ios/Layouts/Tabs/ANNTabsDesign.mm +9 -1
- package/ios/Layouts/Tabs/UITabBar+utils.h +5 -5
- package/ios/Layouts/Tabs/UITabBar+utils.mm +32 -13
- package/ios/Options/ANNAnimationOptions.h +2 -1
- package/ios/Options/ANNAnimationOptions.mm +1 -1
- package/ios/Options/ANNBottomTabsOptions.h +2 -0
- package/ios/Options/ANNBottomTabsOptions.mm +1 -0
- package/ios/Options/ANNOptions.h +25 -0
- package/ios/Options/ANNOptions.mm +157 -1
- package/ios/Options/ANNOptionsCache.h +7 -6
- package/ios/Options/ANNOptionsReader.mm +108 -0
- package/ios/Options/ANNSearchBarOptions.h +4 -3
- package/ios/Options/ANNSheetOptions.h +4 -1
- package/ios/Options/ANNSideMenuOptions.h +2 -0
- package/ios/Options/ANNSideMenuOptions.mm +2 -0
- package/ios/Options/ANNStackPopAnimationOptions.h +13 -0
- package/ios/Options/ANNStackPopAnimationOptions.mm +11 -0
- package/ios/Options/ANNUserChoice.h +57 -0
- package/ios/Options/ANNUserChoice.mm +44 -0
- package/ios/Options/Params/ANNImageSource.h +61 -0
- package/ios/Options/Params/ANNImageSource.mm +101 -0
- package/ios/Options/Params/ANNOptionImages.h +37 -0
- package/ios/Options/Params/ANNOptionImages.mm +284 -0
- package/ios/Options/Params/ANNParam.h +15 -0
- package/ios/Options/Params/ANNParam.mm +61 -0
- package/ios/Options/Params/Color.h +3 -0
- package/ios/Options/Params/Color.mm +21 -0
- package/ios/Options/Params/ColorParser.h +4 -3
- package/ios/Options/Params/ColorParser.mm +22 -4
- package/ios/Options/Params/Image.h +15 -2
- package/ios/Options/Params/Image.mm +35 -2
- package/ios/Options/Params/ImageParser.h +5 -5
- package/ios/Options/Params/ImageParser.mm +28 -46
- package/ios/Public/ApexNavigation/ANNSceneDelegate.h +3 -0
- package/ios/Public/ApexNavigation/ApexNavigation.h +1 -1
- package/ios/RECIPES.md +13 -6
- package/ios/React/ANNReactView.mm +6 -25
- package/ios/React/ANNSafeAreaViewComponentView.mm +28 -17
- package/ios/React/ANNSurfaceHostingView.h +14 -0
- package/ios/React/ANNSurfaceHostingView.mm +144 -1
- package/ios/React/Slots/ANNSlotComponentView.mm +24 -17
- package/ios/React/Slots/ANNSlotContainers.h +14 -6
- package/ios/React/Slots/ANNSlotContainers.mm +75 -2
- package/ios/React/Slots/ANNSlotHost.mm +1 -3
- package/ios/React/Slots/ANNSlotScreenView.mm +8 -2
- package/ios/TopBar/ANNBackButtonPresenter.mm +6 -5
- package/ios/TopBar/ANNBarAppearance.h +2 -1
- package/ios/TopBar/ANNBarAppearance.mm +111 -30
- package/ios/TopBar/ANNBarBackgroundComponent.mm +16 -0
- package/ios/TopBar/ANNBarButtonComponentView.h +4 -4
- package/ios/TopBar/ANNBarButtonComponentView.mm +1 -1
- package/ios/TopBar/ANNBarButtons.h +14 -8
- package/ios/TopBar/ANNBarButtons.mm +397 -80
- package/ios/TopBar/ANNIconButtonImage.h +1 -0
- package/ios/TopBar/ANNIconButtonImage.mm +34 -1
- package/ios/TopBar/ANNLargeTitlePresenter.h +13 -0
- package/ios/TopBar/ANNLargeTitlePresenter.mm +50 -7
- package/ios/TopBar/ANNMainList.h +3 -0
- package/ios/TopBar/ANNMainList.mm +4 -0
- package/ios/TopBar/ANNScrollEdgeEffects.h +22 -6
- package/ios/TopBar/ANNScrollEdgeEffects.mm +123 -16
- package/ios/TopBar/ANNSearchPresenter.mm +172 -21
- package/ios/TopBar/ANNSearchResultsViewController.mm +29 -6
- package/ios/TopBar/ANNTopBarPresenter.h +8 -2
- package/ios/TopBar/ANNTopBarPresenter.mm +155 -33
- package/ios/TurboModules/ANNTurboEventEmitter.mm +4 -35
- package/ios/TurboModules/ANNTurboModule.mm +104 -33
- package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.cpp +20 -0
- package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.h +5 -14
- package/lib/module/ARCHITECTURE.md +40 -27
- package/lib/module/adapters/NativeANNTurboModule.js.map +1 -1
- package/lib/module/api/app/AppRegistry.js +14 -2
- package/lib/module/api/app/AppRegistry.js.map +1 -1
- package/lib/module/api/app/createNavigation.js +190 -66
- package/lib/module/api/app/createNavigation.js.map +1 -1
- package/lib/module/api/commands/commands.js +54 -6
- package/lib/module/api/commands/commands.js.map +1 -1
- package/lib/module/api/events/navigationEvents.js +6 -2
- package/lib/module/api/events/navigationEvents.js.map +1 -1
- package/lib/module/api/hooks/useNavigation.js +8 -3
- package/lib/module/api/hooks/useNavigation.js.map +1 -1
- package/lib/module/api/hooks/useSafeAreaInsets.js +4 -3
- package/lib/module/api/hooks/useSafeAreaInsets.js.map +1 -1
- package/lib/module/api/linking/dispatchedLinks.js +23 -0
- package/lib/module/api/linking/dispatchedLinks.js.map +1 -0
- package/lib/module/api/linking/linking.js +11 -0
- package/lib/module/api/linking/linking.js.map +1 -1
- package/lib/module/api/navigation.js.map +1 -1
- package/lib/module/api/options/OptionsChain.js +2 -2
- package/lib/module/api/screens/defineScreen.js +45 -3
- package/lib/module/api/screens/defineScreen.js.map +1 -1
- package/lib/module/api/screens/nativeScreens.js +31 -6
- package/lib/module/api/screens/nativeScreens.js.map +1 -1
- package/lib/module/api/screens/registerScreens.js +193 -35
- package/lib/module/api/screens/registerScreens.js.map +1 -1
- package/lib/module/api/theme/theme.js +5 -0
- package/lib/module/api/theme/theme.js.map +1 -1
- package/lib/module/engine/commands.js +51 -9
- package/lib/module/engine/commands.js.map +1 -1
- package/lib/module/engine/layout.js +20 -11
- package/lib/module/engine/layout.js.map +1 -1
- package/lib/module/engine/nativeScreens.js +9 -0
- package/lib/module/engine/nativeScreens.js.map +1 -1
- package/lib/module/engine/options.js +49 -15
- package/lib/module/engine/options.js.map +1 -1
- package/lib/module/engine/optionsChange.js +102 -0
- package/lib/module/engine/optionsChange.js.map +1 -0
- package/lib/module/engine/places.js +52 -7
- package/lib/module/engine/places.js.map +1 -1
- package/lib/module/engine/props.js +30 -1
- package/lib/module/engine/props.js.map +1 -1
- package/lib/module/engine/refresh.js +85 -0
- package/lib/module/engine/refresh.js.map +1 -0
- package/lib/module/engine/rememberedOptions.js +61 -1
- package/lib/module/engine/rememberedOptions.js.map +1 -1
- package/lib/module/engine/screens.js +77 -16
- package/lib/module/engine/screens.js.map +1 -1
- package/lib/module/interfaces/contract/commands.json +101 -0
- package/lib/module/interfaces/contract/errors.json +275 -0
- package/lib/typescript/adapters/NativeANNTurboModule.d.ts +12 -2
- package/lib/typescript/adapters/NativeANNTurboModule.d.ts.map +1 -1
- package/lib/typescript/api/app/AppRegistry.d.ts.map +1 -1
- package/lib/typescript/api/app/createNavigation.d.ts +8 -3
- package/lib/typescript/api/app/createNavigation.d.ts.map +1 -1
- package/lib/typescript/api/commands/commands.d.ts.map +1 -1
- package/lib/typescript/api/commands/presentation.d.ts +4 -3
- package/lib/typescript/api/commands/presentation.d.ts.map +1 -1
- package/lib/typescript/api/events/navigationEvents.d.ts +3 -3
- package/lib/typescript/api/events/navigationEvents.d.ts.map +1 -1
- package/lib/typescript/api/hooks/useNavigation.d.ts +1 -1
- package/lib/typescript/api/hooks/useNavigation.d.ts.map +1 -1
- package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts +4 -3
- package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts.map +1 -1
- package/lib/typescript/api/index.d.ts +1 -1
- package/lib/typescript/api/index.d.ts.map +1 -1
- package/lib/typescript/api/linking/dispatchedLinks.d.ts +7 -0
- package/lib/typescript/api/linking/dispatchedLinks.d.ts.map +1 -0
- package/lib/typescript/api/linking/linking.d.ts +8 -0
- package/lib/typescript/api/linking/linking.d.ts.map +1 -1
- package/lib/typescript/api/navigation.d.ts +4 -1
- package/lib/typescript/api/navigation.d.ts.map +1 -1
- package/lib/typescript/api/options/OptionsChain.d.ts +2 -2
- package/lib/typescript/api/screens/defineScreen.d.ts +23 -4
- package/lib/typescript/api/screens/defineScreen.d.ts.map +1 -1
- package/lib/typescript/api/screens/nativeScreens.d.ts +8 -1
- package/lib/typescript/api/screens/nativeScreens.d.ts.map +1 -1
- package/lib/typescript/api/screens/registerScreens.d.ts.map +1 -1
- package/lib/typescript/api/theme/theme.d.ts +2 -0
- package/lib/typescript/api/theme/theme.d.ts.map +1 -1
- package/lib/typescript/engine/commands.d.ts +5 -0
- package/lib/typescript/engine/commands.d.ts.map +1 -1
- package/lib/typescript/engine/layout.d.ts.map +1 -1
- package/lib/typescript/engine/nativeScreens.d.ts +5 -0
- package/lib/typescript/engine/nativeScreens.d.ts.map +1 -1
- package/lib/typescript/engine/options.d.ts +5 -2
- package/lib/typescript/engine/options.d.ts.map +1 -1
- package/lib/typescript/engine/optionsChange.d.ts +28 -0
- package/lib/typescript/engine/optionsChange.d.ts.map +1 -0
- package/lib/typescript/engine/places.d.ts +7 -2
- package/lib/typescript/engine/places.d.ts.map +1 -1
- package/lib/typescript/engine/props.d.ts +8 -1
- package/lib/typescript/engine/props.d.ts.map +1 -1
- package/lib/typescript/engine/refresh.d.ts +35 -0
- package/lib/typescript/engine/refresh.d.ts.map +1 -0
- package/lib/typescript/engine/rememberedOptions.d.ts +13 -0
- package/lib/typescript/engine/rememberedOptions.d.ts.map +1 -1
- package/lib/typescript/engine/screens.d.ts +27 -6
- package/lib/typescript/engine/screens.d.ts.map +1 -1
- package/lib/typescript/interfaces/ComponentEvents.d.ts +4 -4
- package/lib/typescript/interfaces/ComponentEvents.d.ts.map +1 -1
- package/lib/typescript/interfaces/Events.d.ts +28 -10
- package/lib/typescript/interfaces/Events.d.ts.map +1 -1
- package/lib/typescript/interfaces/Options.d.ts +1 -1
- package/lib/typescript/interfaces/Options.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/animations.d.ts +80 -22
- package/lib/typescript/interfaces/options/animations.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/bottomTabs.d.ts +21 -7
- package/lib/typescript/interfaces/options/bottomTabs.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/buttons.d.ts +23 -15
- package/lib/typescript/interfaces/options/buttons.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/modals.d.ts +34 -26
- package/lib/typescript/interfaces/options/modals.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/sideMenu.d.ts +23 -6
- package/lib/typescript/interfaces/options/sideMenu.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/stack.d.ts +17 -3
- package/lib/typescript/interfaces/options/stack.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/system.d.ts +18 -11
- package/lib/typescript/interfaces/options/system.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/toolbar.d.ts +2 -2
- package/lib/typescript/interfaces/options/topBar.d.ts +68 -38
- package/lib/typescript/interfaces/options/topBar.d.ts.map +1 -1
- package/metro/acceptPlugin.js +57 -0
- package/metro/babelTransformer.js +45 -0
- package/metro/index.js +36 -0
- package/package.json +4 -25
- package/src/ARCHITECTURE.md +40 -27
- package/src/adapters/NativeANNTurboModule.ts +12 -2
- package/src/api/app/AppRegistry.ts +16 -2
- package/src/api/app/createNavigation.ts +203 -69
- package/src/api/commands/commands.ts +48 -7
- package/src/api/commands/presentation.ts +4 -3
- package/src/api/events/navigationEvents.ts +10 -4
- package/src/api/hooks/useNavigation.ts +9 -4
- package/src/api/hooks/useSafeAreaInsets.ts +4 -3
- package/src/api/index.ts +1 -0
- package/src/api/linking/dispatchedLinks.ts +18 -0
- package/src/api/linking/linking.ts +22 -1
- package/src/api/navigation.ts +4 -1
- package/src/api/options/OptionsChain.ts +2 -2
- package/src/api/screens/defineScreen.ts +49 -5
- package/src/api/screens/nativeScreens.ts +40 -4
- package/src/api/screens/registerScreens.tsx +185 -42
- package/src/api/theme/theme.ts +5 -0
- package/src/engine/commands.ts +70 -13
- package/src/engine/layout.ts +27 -11
- package/src/engine/nativeScreens.ts +10 -1
- package/src/engine/options.ts +45 -19
- package/src/engine/optionsChange.ts +107 -0
- package/src/engine/places.ts +65 -7
- package/src/engine/props.ts +30 -1
- package/src/engine/refresh.ts +97 -0
- package/src/engine/rememberedOptions.ts +74 -1
- package/src/engine/screens.tsx +76 -21
- package/src/interfaces/ComponentEvents.ts +4 -4
- package/src/interfaces/Events.ts +29 -10
- package/src/interfaces/Options.ts +1 -0
- package/src/interfaces/contract/commands.json +101 -0
- package/src/interfaces/contract/errors.json +275 -0
- package/src/interfaces/options/animations.ts +81 -22
- package/src/interfaces/options/bottomTabs.ts +21 -7
- package/src/interfaces/options/buttons.ts +23 -15
- package/src/interfaces/options/modals.ts +34 -26
- package/src/interfaces/options/sideMenu.ts +24 -6
- package/src/interfaces/options/stack.ts +17 -3
- package/src/interfaces/options/system.ts +18 -11
- package/src/interfaces/options/toolbar.ts +2 -2
- package/src/interfaces/options/topBar.ts +68 -38
- package/android/src/main/java/dev/apexnative/navigation/react/ArrangementStates.kt +0 -41
- package/android/src/main/java/dev/apexnative/navigation/react/ScreenInsets.kt +0 -69
- package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationStateReporter.kt +0 -62
- package/android/src/main/java/dev/apexnative/navigation/react/events/StateHold.kt +0 -62
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowPlacer.kt +0 -223
- package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStub.kt +0 -31
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMatrixAnimator.kt +0 -138
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PlainViewAnimator.kt +0 -88
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PropertyAnimatorCreator.kt +0 -33
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ReactImageAnimator.kt +0 -66
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextChangeAnimator.kt +0 -179
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewChangeAnimator.kt +0 -139
- package/ios/Layouts/Screen/ANNScreenInsets.h +0 -30
- package/ios/Layouts/Screen/ANNScreenInsets.mm +0 -68
- package/ios/Layouts/Tabs/ANNTabsPreloadWindow.h +0 -27
- package/ios/Layouts/Tabs/ANNTabsPreloadWindow.mm +0 -55
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
#import "ANNScreenEnvironment.h"
|
|
2
|
+
#import "ANNEventContract.h"
|
|
3
|
+
|
|
4
|
+
// One screen's record; nil for a fact not known yet (not laid out, no regions, outside a pair). Changed and read only
|
|
5
|
+
// under the lock of `ANNEnvironmentById`; the values are immutable, so a reader keeps what it took.
|
|
6
|
+
@interface ANNScreenEnvironmentRecord : NSObject
|
|
7
|
+
@property(nonatomic, copy, nullable) NSDictionary<NSString *, NSNumber *> *insets;
|
|
8
|
+
@property(nonatomic, strong, nullable) NSValue *padding;
|
|
9
|
+
@property(nonatomic, copy, nullable) NSDictionary<NSString *, NSArray *> *regions;
|
|
10
|
+
@property(nonatomic, copy, nullable) NSDictionary<NSString *, id> *arrangement;
|
|
11
|
+
@end
|
|
12
|
+
|
|
13
|
+
@implementation ANNScreenEnvironmentRecord
|
|
14
|
+
@end
|
|
15
|
+
|
|
16
|
+
// Written on the main queue, read from any thread: every access holds its lock.
|
|
17
|
+
static NSMutableDictionary<NSString *, ANNScreenEnvironmentRecord *> *ANNEnvironmentById;
|
|
18
|
+
// The safe area views of each screen, by its id (the id's value: the view's id and the core's are other strings), held
|
|
19
|
+
// weakly. Main queue only.
|
|
20
|
+
static NSMutableDictionary<NSString *, NSHashTable<id<ANNScreenPaddingListener>> *>
|
|
21
|
+
*ANNPaddingListenersById;
|
|
22
|
+
|
|
23
|
+
@implementation ANNScreenEnvironment
|
|
24
|
+
|
|
25
|
+
+ (void)initialize {
|
|
26
|
+
if (self == ANNScreenEnvironment.class) {
|
|
27
|
+
ANNEnvironmentById = [NSMutableDictionary new];
|
|
28
|
+
ANNPaddingListenersById = [NSMutableDictionary new];
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// The screen's record, a new one for a screen not kept yet. Under the lock.
|
|
33
|
+
+ (ANNScreenEnvironmentRecord *)recordOf:(NSString *)screenId {
|
|
34
|
+
ANNScreenEnvironmentRecord *record = ANNEnvironmentById[screenId];
|
|
35
|
+
if (!record) {
|
|
36
|
+
record = [ANNScreenEnvironmentRecord new];
|
|
37
|
+
ANNEnvironmentById[screenId] = record;
|
|
38
|
+
}
|
|
39
|
+
return record;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
#pragma mark - Insets and padding
|
|
43
|
+
|
|
44
|
+
+ (void)setInsets:(UIEdgeInsets)insets
|
|
45
|
+
padding:(UIEdgeInsets)padding
|
|
46
|
+
forScreenId:(NSString *)screenId
|
|
47
|
+
eventEmitter:(ANNEventEmitter *)eventEmitter {
|
|
48
|
+
NSValue *paddingValue = [NSValue valueWithUIEdgeInsets:padding];
|
|
49
|
+
// JavaScript gets what still covers the content: the edges the safe area view keeps it off are 0.
|
|
50
|
+
const auto &keys = ANNEventContract.ScreenInsetsChanged;
|
|
51
|
+
NSDictionary<NSString *, NSNumber *> *value = @{
|
|
52
|
+
keys.top : @(MAX(insets.top - padding.top, 0)),
|
|
53
|
+
keys.right : @(MAX(insets.right - padding.right, 0)),
|
|
54
|
+
keys.bottom : @(MAX(insets.bottom - padding.bottom, 0)),
|
|
55
|
+
keys.left : @(MAX(insets.left - padding.left, 0)),
|
|
56
|
+
};
|
|
57
|
+
BOOL paddingChanged;
|
|
58
|
+
BOOL insetsChanged;
|
|
59
|
+
@synchronized(ANNEnvironmentById) {
|
|
60
|
+
ANNScreenEnvironmentRecord *record = [self recordOf:screenId];
|
|
61
|
+
paddingChanged = ![record.padding isEqualToValue:paddingValue];
|
|
62
|
+
insetsChanged = ![record.insets isEqualToDictionary:value];
|
|
63
|
+
record.padding = paddingValue;
|
|
64
|
+
record.insets = value;
|
|
65
|
+
}
|
|
66
|
+
// The listeners read the padding back, so it is kept before they are told. A copy: a listener may stop or start
|
|
67
|
+
// listening while it is told.
|
|
68
|
+
if (paddingChanged) {
|
|
69
|
+
NSHashTable<id<ANNScreenPaddingListener>> *listeners = ANNPaddingListenersById[screenId];
|
|
70
|
+
for (id<ANNScreenPaddingListener> listener in listeners.allObjects) {
|
|
71
|
+
[listener screenPaddingDidChange];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (insetsChanged) {
|
|
75
|
+
[eventEmitter sendScreenInsetsChanged:screenId insets:value];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
+ (UIEdgeInsets)paddingForScreenId:(NSString *)screenId {
|
|
80
|
+
@synchronized(ANNEnvironmentById) {
|
|
81
|
+
return ANNEnvironmentById[screenId].padding.UIEdgeInsetsValue;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
+ (NSDictionary<NSString *, NSNumber *> *)insetsForScreenId:(NSString *)screenId {
|
|
86
|
+
@synchronized(ANNEnvironmentById) {
|
|
87
|
+
return ANNEnvironmentById[screenId].insets;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
#pragma mark - Regions
|
|
92
|
+
|
|
93
|
+
+ (void)setRegions:(NSDictionary<NSString *, NSArray *> *)regions
|
|
94
|
+
forScreenId:(NSString *)screenId
|
|
95
|
+
eventEmitter:(ANNEventEmitter *)eventEmitter {
|
|
96
|
+
const auto &keys = ANNEventContract.ScreenRegionsChanged;
|
|
97
|
+
BOOL empty = [regions[keys.division] count] == 0 && [regions[keys.occlusion] count] == 0;
|
|
98
|
+
@synchronized(ANNEnvironmentById) {
|
|
99
|
+
NSDictionary<NSString *, NSArray *> *before = ANNEnvironmentById[screenId].regions;
|
|
100
|
+
if ((!before && empty) || [before isEqualToDictionary:regions]) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
[self recordOf:screenId].regions = regions;
|
|
104
|
+
}
|
|
105
|
+
[eventEmitter sendScreenRegionsChanged:screenId regions:regions];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
+ (NSDictionary<NSString *, NSArray *> *)regionsForScreenId:(NSString *)screenId {
|
|
109
|
+
@synchronized(ANNEnvironmentById) {
|
|
110
|
+
return ANNEnvironmentById[screenId].regions;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
#pragma mark - Arrangement
|
|
115
|
+
|
|
116
|
+
+ (void)setArrangement:(NSDictionary<NSString *, id> *)arrangement
|
|
117
|
+
forScreenId:(NSString *)screenId
|
|
118
|
+
eventEmitter:(ANNEventEmitter *)eventEmitter {
|
|
119
|
+
@synchronized(ANNEnvironmentById) {
|
|
120
|
+
ANNScreenEnvironmentRecord *record = [self recordOf:screenId];
|
|
121
|
+
if ([record.arrangement isEqualToDictionary:arrangement]) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
record.arrangement = arrangement;
|
|
125
|
+
}
|
|
126
|
+
[eventEmitter sendArrangementChanged:screenId state:arrangement];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
+ (NSDictionary<NSString *, id> *)arrangementForScreenId:(NSString *)screenId {
|
|
130
|
+
@synchronized(ANNEnvironmentById) {
|
|
131
|
+
return ANNEnvironmentById[screenId].arrangement;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
#pragma mark - Padding listeners
|
|
136
|
+
|
|
137
|
+
+ (void)addPaddingListener:(id<ANNScreenPaddingListener>)listener
|
|
138
|
+
forScreenId:(NSString *)screenId {
|
|
139
|
+
NSHashTable<id<ANNScreenPaddingListener>> *listeners = ANNPaddingListenersById[screenId];
|
|
140
|
+
if (!listeners) {
|
|
141
|
+
listeners = [NSHashTable weakObjectsHashTable];
|
|
142
|
+
ANNPaddingListenersById[screenId] = listeners;
|
|
143
|
+
}
|
|
144
|
+
[listeners addObject:listener];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
+ (void)removePaddingListener:(id<ANNScreenPaddingListener>)listener
|
|
148
|
+
forScreenId:(NSString *)screenId {
|
|
149
|
+
NSHashTable<id<ANNScreenPaddingListener>> *listeners = ANNPaddingListenersById[screenId];
|
|
150
|
+
[listeners removeObject:listener];
|
|
151
|
+
[self forgetListenersOfScreenIdIfNone:screenId];
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// A view that went (it doesn't remove itself in its `dealloc`) leaves no entry in the weak table: `allObjects` counts
|
|
155
|
+
// only the live ones. The table of a screen nobody listens to goes with the last one, or with the screen's record.
|
|
156
|
+
+ (void)forgetListenersOfScreenIdIfNone:(NSString *)screenId {
|
|
157
|
+
NSHashTable<id<ANNScreenPaddingListener>> *listeners = ANNPaddingListenersById[screenId];
|
|
158
|
+
if (listeners && listeners.allObjects.count == 0) {
|
|
159
|
+
[ANNPaddingListenersById removeObjectForKey:screenId];
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
#pragma mark - Removal
|
|
164
|
+
|
|
165
|
+
+ (void)removeScreenId:(NSString *)screenId {
|
|
166
|
+
@synchronized(ANNEnvironmentById) {
|
|
167
|
+
[ANNEnvironmentById removeObjectForKey:screenId];
|
|
168
|
+
}
|
|
169
|
+
[self forgetListenersOfScreenIdIfNone:screenId];
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
+ (void)removeAll {
|
|
173
|
+
@synchronized(ANNEnvironmentById) {
|
|
174
|
+
[ANNEnvironmentById removeAllObjects];
|
|
175
|
+
}
|
|
176
|
+
for (NSString *screenId in ANNPaddingListenersById.allKeys) {
|
|
177
|
+
[self forgetListenersOfScreenIdIfNone:screenId];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
@end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#import "ANNNavigationOptions.h"
|
|
2
|
+
#import <UIKit/UIKit.h>
|
|
3
|
+
|
|
4
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
5
|
+
|
|
6
|
+
/// Where an entry will show on top of a stack, as UIKit lays it out there: the safe area its screens get, and whether
|
|
7
|
+
/// the stack's bar and the tab bar show for it. A screen that waits for its content out of its stack (parked,
|
|
8
|
+
/// `ANNParking`) has no parent view controller, and UIKit gives its view no safe area at all: it lays out with its
|
|
9
|
+
/// place's instead (`placeWhileParked` of `ANNComponentViewController`), so that its root frame, its padding, the
|
|
10
|
+
/// insets JavaScript reads in its first render and its main list are those it has after the push. Nothing of it moves
|
|
11
|
+
/// as the push starts: a list that moved then would lose the large title, which UIKit draws in the list the bar
|
|
12
|
+
/// follows.
|
|
13
|
+
///
|
|
14
|
+
/// The bar's height is UIKit's own: a navigation controller of the core's, unseen in the stack's view for the moment of
|
|
15
|
+
/// the measure, shows an item made like the entry's (title, display mode of the large title, looks, subtitles, prompt,
|
|
16
|
+
/// style, search field) over one like the stack's top, with the stack's bar settings and the entry's toolbar. Main
|
|
17
|
+
/// queue.
|
|
18
|
+
@interface ANNScreenPlace : NSObject
|
|
19
|
+
|
|
20
|
+
- (instancetype)init NS_UNAVAILABLE;
|
|
21
|
+
+ (instancetype)new NS_UNAVAILABLE;
|
|
22
|
+
|
|
23
|
+
/// The place of `entry` (a screen, or a pair whose screens show under its bar) on top of `stack`, with `options` the
|
|
24
|
+
/// resolved options the stack shows its bar and toolbar by; nil when the stack isn't in a window. Measured again only
|
|
25
|
+
/// when something the measure reads changed since the last one for `entry`.
|
|
26
|
+
+ (nullable ANNScreenPlace *)placeOfEntry:(UIViewController *)entry
|
|
27
|
+
inStack:(UINavigationController *)stack
|
|
28
|
+
options:(ANNNavigationOptions *)options;
|
|
29
|
+
|
|
30
|
+
/// The same, measured in `host` instead of the stack's view: for a stack UIKit gives no safe area yet (a tab not shown,
|
|
31
|
+
/// parked in the tabs' view), `host` is a view with the safe area the stack gets as it shows (the shown tab's). Nil
|
|
32
|
+
/// when `host` isn't in a window.
|
|
33
|
+
+ (nullable ANNScreenPlace *)placeOfEntry:(UIViewController *)entry
|
|
34
|
+
inStack:(UINavigationController *)stack
|
|
35
|
+
measuredIn:(UIView *)host
|
|
36
|
+
options:(ANNNavigationOptions *)options;
|
|
37
|
+
|
|
38
|
+
/// The place of a screen that is a tab of its own, with no stack: the safe area of `host` (the shown tab's view), no
|
|
39
|
+
/// top bar. Nil when `host` isn't in a window.
|
|
40
|
+
+ (nullable ANNScreenPlace *)placeOfScreen:(UIViewController *)screen measuredIn:(UIView *)host;
|
|
41
|
+
|
|
42
|
+
/// The safe area of the entry's view in the place.
|
|
43
|
+
@property(nonatomic, readonly) UIEdgeInsets safeArea;
|
|
44
|
+
|
|
45
|
+
/// The stack's bar shows for the entry (`topBar.visible`).
|
|
46
|
+
@property(nonatomic, readonly) BOOL showsTopBar;
|
|
47
|
+
|
|
48
|
+
/// A tab bar shows at the bottom for the entry: one shows now and the entry doesn't hide it.
|
|
49
|
+
@property(nonatomic, readonly) BOOL showsTabBar;
|
|
50
|
+
|
|
51
|
+
@end
|
|
52
|
+
|
|
53
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
#import "ANNScreenPlace.h"
|
|
2
|
+
#import "ANNAssert.h"
|
|
3
|
+
#import "ANNBottomTabsController.h"
|
|
4
|
+
#import <objc/runtime.h>
|
|
5
|
+
|
|
6
|
+
static const void *ANNScreenPlaceKey = &ANNScreenPlaceKey;
|
|
7
|
+
|
|
8
|
+
// The measuring navigation controller of each stack: its first item stands for the stack's top, the second for the
|
|
9
|
+
// entry. Weak keys: it goes with its stack.
|
|
10
|
+
static NSMapTable<UINavigationController *, UINavigationController *> *ANNPlaceProbes(void) {
|
|
11
|
+
static NSMapTable<UINavigationController *, UINavigationController *> *probes;
|
|
12
|
+
if (!probes) {
|
|
13
|
+
probes = [NSMapTable weakToStrongObjectsMapTable];
|
|
14
|
+
}
|
|
15
|
+
return probes;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static UINavigationController *ANNPlaceProbeOf(UINavigationController *stack) {
|
|
19
|
+
UINavigationController *probe = [ANNPlaceProbes() objectForKey:stack];
|
|
20
|
+
if (!probe) {
|
|
21
|
+
probe = [[UINavigationController alloc] initWithRootViewController:[UIViewController new]];
|
|
22
|
+
[probe pushViewController:[UIViewController new] animated:NO];
|
|
23
|
+
[ANNPlaceProbes() setObject:probe forKey:stack];
|
|
24
|
+
}
|
|
25
|
+
return probe;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// What UIKit sizes the bar by, from the entry's item. The search field is a field of its own with the same placement:
|
|
29
|
+
// a search controller shows in one item only.
|
|
30
|
+
static void ANNCopyBarItem(UINavigationItem *from, UINavigationItem *to) {
|
|
31
|
+
to.title = from.title;
|
|
32
|
+
to.prompt = from.prompt;
|
|
33
|
+
to.largeTitleDisplayMode = from.largeTitleDisplayMode;
|
|
34
|
+
to.standardAppearance = from.standardAppearance;
|
|
35
|
+
to.scrollEdgeAppearance = from.scrollEdgeAppearance;
|
|
36
|
+
to.compactAppearance = from.compactAppearance;
|
|
37
|
+
to.compactScrollEdgeAppearance = from.compactScrollEdgeAppearance;
|
|
38
|
+
to.hidesSearchBarWhenScrolling = from.hidesSearchBarWhenScrolling;
|
|
39
|
+
to.searchController =
|
|
40
|
+
from.searchController ? [[UISearchController alloc] initWithSearchResultsController:nil] : nil;
|
|
41
|
+
if (@available(iOS 16.0, *)) {
|
|
42
|
+
to.style = from.style;
|
|
43
|
+
to.preferredSearchBarPlacement = from.preferredSearchBarPlacement;
|
|
44
|
+
}
|
|
45
|
+
if (@available(iOS 26.0, *)) {
|
|
46
|
+
to.attributedSubtitle = from.attributedSubtitle;
|
|
47
|
+
to.largeAttributedSubtitle = from.largeAttributedSubtitle;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Everything the measure reads: the same answer while none of it changed.
|
|
52
|
+
static NSString *ANNPlaceSignature(UINavigationItem *item, UINavigationController *stack,
|
|
53
|
+
UIView *host, BOOL showsTopBar, BOOL showsToolbar) {
|
|
54
|
+
NSMutableString *signature = [NSMutableString
|
|
55
|
+
stringWithFormat:@"%@|%@|%ld|%p|%p|%p|%p|%p|%d|%d|%d|%d|%@|%@", item.title, item.prompt,
|
|
56
|
+
(long)item.largeTitleDisplayMode, item.standardAppearance,
|
|
57
|
+
item.scrollEdgeAppearance, item.compactAppearance,
|
|
58
|
+
item.compactScrollEdgeAppearance, item.searchController,
|
|
59
|
+
item.hidesSearchBarWhenScrolling, stack.navigationBar.prefersLargeTitles,
|
|
60
|
+
showsTopBar, showsToolbar, NSStringFromCGSize(host.bounds.size),
|
|
61
|
+
NSStringFromUIEdgeInsets(host.safeAreaInsets)];
|
|
62
|
+
[signature appendFormat:@"|%p|%ld", stack,
|
|
63
|
+
(long)stack.topViewController.navigationItem.largeTitleDisplayMode];
|
|
64
|
+
if (@available(iOS 16.0, *)) {
|
|
65
|
+
[signature appendFormat:@"|%ld|%ld", (long)item.style, (long)item.preferredSearchBarPlacement];
|
|
66
|
+
}
|
|
67
|
+
if (@available(iOS 26.0, *)) {
|
|
68
|
+
[signature appendFormat:@"|%@|%@", item.attributedSubtitle, item.largeAttributedSubtitle];
|
|
69
|
+
}
|
|
70
|
+
return signature;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@implementation ANNScreenPlace {
|
|
74
|
+
NSString *_signature;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
- (instancetype)initWithSafeArea:(UIEdgeInsets)safeArea
|
|
78
|
+
showsTopBar:(BOOL)showsTopBar
|
|
79
|
+
showsTabBar:(BOOL)showsTabBar
|
|
80
|
+
signature:(NSString *)signature {
|
|
81
|
+
if (self = [super init]) {
|
|
82
|
+
_safeArea = safeArea;
|
|
83
|
+
_showsTopBar = showsTopBar;
|
|
84
|
+
_showsTabBar = showsTabBar;
|
|
85
|
+
_signature = [signature copy];
|
|
86
|
+
}
|
|
87
|
+
return self;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
+ (ANNScreenPlace *)placeOfEntry:(UIViewController *)entry
|
|
91
|
+
inStack:(UINavigationController *)stack
|
|
92
|
+
options:(ANNNavigationOptions *)options {
|
|
93
|
+
UIView *stackView = stack.viewIfLoaded;
|
|
94
|
+
if (!stackView) {
|
|
95
|
+
return nil;
|
|
96
|
+
}
|
|
97
|
+
return [self placeOfEntry:entry inStack:stack measuredIn:stackView options:options];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
+ (ANNScreenPlace *)placeOfEntry:(UIViewController *)entry
|
|
101
|
+
inStack:(UINavigationController *)stack
|
|
102
|
+
measuredIn:(UIView *)host
|
|
103
|
+
options:(ANNNavigationOptions *)options {
|
|
104
|
+
ANNAssertMainQueue();
|
|
105
|
+
UIWindow *window = host.window;
|
|
106
|
+
if (!window) {
|
|
107
|
+
return nil;
|
|
108
|
+
}
|
|
109
|
+
BOOL showsTopBar = [options.topBar.visible withDefault:YES];
|
|
110
|
+
BOOL showsToolbar = options.toolbar.shouldShow;
|
|
111
|
+
BOOL showsTabBar = !entry.hidesBottomBarWhenPushed &&
|
|
112
|
+
[[ANNBottomTabsController tabsOf:entry] showsTabBarForScreen:entry];
|
|
113
|
+
NSString *signature =
|
|
114
|
+
ANNPlaceSignature(entry.navigationItem, stack, host, showsTopBar, showsToolbar);
|
|
115
|
+
ANNScreenPlace *kept = objc_getAssociatedObject(entry, ANNScreenPlaceKey);
|
|
116
|
+
if (kept && kept.showsTabBar == showsTabBar && [kept->_signature isEqualToString:signature]) {
|
|
117
|
+
return kept;
|
|
118
|
+
}
|
|
119
|
+
UIEdgeInsets safeArea = [self measureEntry:entry
|
|
120
|
+
inStack:stack
|
|
121
|
+
host:host
|
|
122
|
+
showsTopBar:showsTopBar
|
|
123
|
+
showsToolbar:showsToolbar];
|
|
124
|
+
// The measure stands in the host, whose safe area has the tab bar shown now: an entry that hides it gets the
|
|
125
|
+
// window's bottom there.
|
|
126
|
+
if (!showsTabBar) {
|
|
127
|
+
CGFloat tabBar = host.safeAreaInsets.bottom - window.safeAreaInsets.bottom;
|
|
128
|
+
if (tabBar > 0) {
|
|
129
|
+
safeArea.bottom = MAX(safeArea.bottom - tabBar, 0);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
ANNScreenPlace *place = [[ANNScreenPlace alloc] initWithSafeArea:safeArea
|
|
133
|
+
showsTopBar:showsTopBar
|
|
134
|
+
showsTabBar:showsTabBar
|
|
135
|
+
signature:signature];
|
|
136
|
+
objc_setAssociatedObject(entry, ANNScreenPlaceKey, place, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
137
|
+
return place;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
+ (ANNScreenPlace *)placeOfScreen:(UIViewController *)screen measuredIn:(UIView *)host {
|
|
141
|
+
ANNAssertMainQueue();
|
|
142
|
+
UIWindow *window = host.window;
|
|
143
|
+
if (!window) {
|
|
144
|
+
return nil;
|
|
145
|
+
}
|
|
146
|
+
BOOL showsTabBar = [[ANNBottomTabsController tabsOf:screen] showsTabBarForScreen:screen];
|
|
147
|
+
UIEdgeInsets safeArea = host.safeAreaInsets;
|
|
148
|
+
if (!showsTabBar) {
|
|
149
|
+
CGFloat tabBar = safeArea.bottom - window.safeAreaInsets.bottom;
|
|
150
|
+
if (tabBar > 0) {
|
|
151
|
+
safeArea.bottom = MAX(safeArea.bottom - tabBar, 0);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return [[ANNScreenPlace alloc] initWithSafeArea:safeArea
|
|
155
|
+
showsTopBar:NO
|
|
156
|
+
showsTabBar:showsTabBar
|
|
157
|
+
signature:@""];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// The probe lays out at the host's size in the host, unseen and for this moment only, and leaves no search field
|
|
161
|
+
// behind.
|
|
162
|
+
+ (UIEdgeInsets)measureEntry:(UIViewController *)entry
|
|
163
|
+
inStack:(UINavigationController *)stack
|
|
164
|
+
host:(UIView *)host
|
|
165
|
+
showsTopBar:(BOOL)showsTopBar
|
|
166
|
+
showsToolbar:(BOOL)showsToolbar {
|
|
167
|
+
UINavigationController *probe = ANNPlaceProbeOf(stack);
|
|
168
|
+
UIViewController *below = probe.viewControllers.firstObject;
|
|
169
|
+
UIViewController *top = probe.topViewController;
|
|
170
|
+
UINavigationBar *bar = probe.navigationBar;
|
|
171
|
+
UINavigationBar *stackBar = stack.navigationBar;
|
|
172
|
+
bar.prefersLargeTitles = stackBar.prefersLargeTitles;
|
|
173
|
+
bar.standardAppearance = stackBar.standardAppearance;
|
|
174
|
+
bar.scrollEdgeAppearance = stackBar.scrollEdgeAppearance;
|
|
175
|
+
bar.compactAppearance = stackBar.compactAppearance;
|
|
176
|
+
below.navigationItem.largeTitleDisplayMode =
|
|
177
|
+
stack.topViewController.navigationItem.largeTitleDisplayMode;
|
|
178
|
+
ANNCopyBarItem(entry.navigationItem, top.navigationItem);
|
|
179
|
+
top.toolbarItems =
|
|
180
|
+
showsToolbar ? @[ [[UIBarButtonItem alloc] initWithTitle:@" "
|
|
181
|
+
style:UIBarButtonItemStylePlain
|
|
182
|
+
target:nil
|
|
183
|
+
action:nil] ]
|
|
184
|
+
: nil;
|
|
185
|
+
__block UIEdgeInsets safeArea = UIEdgeInsetsZero;
|
|
186
|
+
UIView *probeView = probe.view;
|
|
187
|
+
[UIView performWithoutAnimation:^{
|
|
188
|
+
[probe setNavigationBarHidden:!showsTopBar animated:NO];
|
|
189
|
+
[probe setToolbarHidden:!showsToolbar animated:NO];
|
|
190
|
+
probeView.alpha = 0;
|
|
191
|
+
probeView.userInteractionEnabled = NO;
|
|
192
|
+
probeView.accessibilityElementsHidden = YES;
|
|
193
|
+
probeView.frame = host.bounds;
|
|
194
|
+
[host insertSubview:probeView atIndex:0];
|
|
195
|
+
[probeView layoutIfNeeded];
|
|
196
|
+
[top.view layoutIfNeeded];
|
|
197
|
+
safeArea = top.view.safeAreaInsets;
|
|
198
|
+
[probeView removeFromSuperview];
|
|
199
|
+
}];
|
|
200
|
+
top.navigationItem.searchController = nil;
|
|
201
|
+
top.toolbarItems = nil;
|
|
202
|
+
return safeArea;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
@end
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
#import "ANNEventEmitter.h"
|
|
2
1
|
#import <UIKit/UIKit.h>
|
|
3
2
|
|
|
4
3
|
NS_ASSUME_NONNULL_BEGIN
|
|
5
4
|
|
|
6
|
-
/// The reserved regions of
|
|
7
|
-
///
|
|
8
|
-
/// `{ x, y, width, height }`.
|
|
9
|
-
/// for a screen's first render, and gets every change as `ANN.ScreenRegionsChanged`.
|
|
5
|
+
/// The reserved regions of a screen (`useReservedRegions`), iOS 27.1: `division`, where the screen divides (the fold of
|
|
6
|
+
/// a partly folded device), and `occlusion`, where hardware covers it (a camera); each a list of
|
|
7
|
+
/// `{ x, y, width, height }`. Measured here; kept for JavaScript by `ANNScreenEnvironment`.
|
|
10
8
|
@interface ANNScreenRegions : NSObject
|
|
11
9
|
|
|
12
10
|
/// The active regions UIKit reserves in `view`, without the margins it adds around them for interactive content, in
|
|
@@ -15,19 +13,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
15
13
|
+ (nullable NSDictionary<NSString *, NSArray *> *)regionsOfView:(UIView *)view
|
|
16
14
|
inCoordinatesOf:(UIView *)coordinateView;
|
|
17
15
|
|
|
18
|
-
/// Keeps the screen's regions and tells when they changed. Main queue.
|
|
19
|
-
+ (void)setRegions:(NSDictionary<NSString *, NSArray *> *)regions
|
|
20
|
-
forScreenId:(NSString *)screenId
|
|
21
|
-
eventEmitter:(ANNEventEmitter *)eventEmitter;
|
|
22
|
-
|
|
23
|
-
/// `{ division, occlusion }`, or nil before the screen was laid out. Any thread.
|
|
24
|
-
+ (nullable NSDictionary<NSString *, NSArray *> *)regionsForScreenId:(NSString *)screenId;
|
|
25
|
-
|
|
26
|
-
+ (void)removeScreenId:(NSString *)screenId;
|
|
27
|
-
|
|
28
|
-
/// Forgets every screen: after a reload the new JavaScript counts its ids anew. Main queue.
|
|
29
|
-
+ (void)removeAll;
|
|
30
|
-
|
|
31
16
|
@end
|
|
32
17
|
|
|
33
18
|
NS_ASSUME_NONNULL_END
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#import "ANNScreenRegions.h"
|
|
2
|
-
|
|
3
|
-
static NSMutableDictionary<NSString *, NSDictionary<NSString *, NSArray *> *> *ANNScreenRegionsById;
|
|
2
|
+
#import "ANNEventContract.h"
|
|
4
3
|
|
|
5
4
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 270100
|
|
6
5
|
// The part of a region inside the screen, CGRectNull for a region outside it (the fold beside a screen of a pair, the
|
|
@@ -36,11 +35,12 @@ ANNRegionRects(NSArray<UIViewReservedRegion *> *regions, UIView *view, UIView *c
|
|
|
36
35
|
if (CGRectIsNull(frame)) {
|
|
37
36
|
continue;
|
|
38
37
|
}
|
|
38
|
+
const auto &keys = ANNEventContract.ScreenRegionRect;
|
|
39
39
|
[rects addObject:@{
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
keys.x : @(frame.origin.x),
|
|
41
|
+
keys.y : @(frame.origin.y),
|
|
42
|
+
keys.width : @(frame.size.width),
|
|
43
|
+
keys.height : @(frame.size.height),
|
|
44
44
|
}];
|
|
45
45
|
}
|
|
46
46
|
return rects;
|
|
@@ -49,12 +49,6 @@ ANNRegionRects(NSArray<UIViewReservedRegion *> *regions, UIView *view, UIView *c
|
|
|
49
49
|
|
|
50
50
|
@implementation ANNScreenRegions
|
|
51
51
|
|
|
52
|
-
+ (void)initialize {
|
|
53
|
-
if (self == ANNScreenRegions.class) {
|
|
54
|
-
ANNScreenRegionsById = [NSMutableDictionary new];
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
52
|
+ (NSDictionary<NSString *, NSArray *> *)regionsOfView:(UIView *)view
|
|
59
53
|
inCoordinatesOf:(UIView *)coordinateView {
|
|
60
54
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 270100
|
|
@@ -63,43 +57,14 @@ ANNRegionRects(NSArray<UIViewReservedRegion *> *regions, UIView *view, UIView *c
|
|
|
63
57
|
[view reservedRegionsOfKind:[UIViewReservedRegionKind divisionRegionKind]];
|
|
64
58
|
NSArray<UIViewReservedRegion *> *occlusion =
|
|
65
59
|
[view reservedRegionsOfKind:[UIViewReservedRegionKind occlusionRegionKind]];
|
|
60
|
+
const auto &keys = ANNEventContract.ScreenRegionsChanged;
|
|
66
61
|
return @{
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
keys.division : ANNRegionRects(division, view, coordinateView),
|
|
63
|
+
keys.occlusion : ANNRegionRects(occlusion, view, coordinateView),
|
|
69
64
|
};
|
|
70
65
|
}
|
|
71
66
|
#endif
|
|
72
67
|
return nil;
|
|
73
68
|
}
|
|
74
69
|
|
|
75
|
-
+ (void)setRegions:(NSDictionary<NSString *, NSArray *> *)regions
|
|
76
|
-
forScreenId:(NSString *)screenId
|
|
77
|
-
eventEmitter:(ANNEventEmitter *)eventEmitter {
|
|
78
|
-
@synchronized(ANNScreenRegionsById) {
|
|
79
|
-
if ([ANNScreenRegionsById[screenId] isEqualToDictionary:regions]) {
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
ANNScreenRegionsById[screenId] = regions;
|
|
83
|
-
}
|
|
84
|
-
[eventEmitter sendScreenRegionsChanged:screenId regions:regions];
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
+ (NSDictionary<NSString *, NSArray *> *)regionsForScreenId:(NSString *)screenId {
|
|
88
|
-
@synchronized(ANNScreenRegionsById) {
|
|
89
|
-
return ANNScreenRegionsById[screenId];
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
+ (void)removeScreenId:(NSString *)screenId {
|
|
94
|
-
@synchronized(ANNScreenRegionsById) {
|
|
95
|
-
[ANNScreenRegionsById removeObjectForKey:screenId];
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
+ (void)removeAll {
|
|
100
|
-
@synchronized(ANNScreenRegionsById) {
|
|
101
|
-
[ANNScreenRegionsById removeAllObjects];
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
70
|
@end
|
|
@@ -7,10 +7,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
7
7
|
typedef struct {
|
|
8
8
|
/// The screen is in a stack.
|
|
9
9
|
BOOL inStack;
|
|
10
|
-
/// The screen's stack shows its toolbar.
|
|
11
|
-
BOOL stackShowsToolbar;
|
|
12
|
-
/// The bottom of the window's safe area: the home indicator.
|
|
13
|
-
CGFloat windowBottomSafeArea;
|
|
14
10
|
/// The physical side of the iPhone Duo vertical bar (iOS 27.1): `UIRectEdgeLeft`, `UIRectEdgeRight`, or
|
|
15
11
|
/// `UIRectEdgeNone` without one.
|
|
16
12
|
UIRectEdge verticalBarSide;
|
|
@@ -27,11 +23,10 @@ FOUNDATION_EXPORT UIEdgeInsets ANNScreenInsetsOverRoot(CGRect rootFrame, CGSize
|
|
|
27
23
|
UIEdgeInsets safeArea);
|
|
28
24
|
|
|
29
25
|
/// The padding the screen's safe area view keeps (`layout.safeAreaEdges`): the insets on the padded edges, 0 on the
|
|
30
|
-
/// others. With `layout.safeAreaEdges` exactly those edges
|
|
31
|
-
/// without it every edge but: the top under a shown top bar (in a stack, under the top
|
|
32
|
-
/// `false`) or with a large title that can show; the bottom
|
|
33
|
-
///
|
|
34
|
-
/// unless `layout.drawBehindVerticalBar` or `layout.verticalBars` is `false`.
|
|
26
|
+
/// others. With `layout.safeAreaEdges` exactly those edges, but the top under a large title that can show (in a stack,
|
|
27
|
+
/// `topBar.visible` not `false`); without it every edge but: the top under a shown top bar (in a stack, under the top
|
|
28
|
+
/// bar, `topBar.visible` not `false`) or with a large title that can show; the bottom, always; the side of the
|
|
29
|
+
/// vertical bar unless `layout.drawBehindVerticalBar` or `layout.verticalBars` is `false`.
|
|
35
30
|
FOUNDATION_EXPORT UIEdgeInsets ANNScreenPadding(UIEdgeInsets insets, ANNNavigationOptions *options,
|
|
36
31
|
ANNScreenPaddingContext context);
|
|
37
32
|
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
#import "ANNScreenSafeArea.h"
|
|
2
2
|
#import "ANNScreenBars.h"
|
|
3
3
|
|
|
4
|
-
// A bar at the bottom covers more than the home indicator when the bottom inset passes it by more than this.
|
|
5
|
-
static const CGFloat ANNBottomBarThreshold = 0.5;
|
|
6
|
-
|
|
7
4
|
CGRect ANNScreenRootFrame(CGRect bounds, UIEdgeInsets safeArea, BOOL fromTop, BOOL toBottom) {
|
|
8
5
|
CGFloat top = fromTop ? 0 : safeArea.top;
|
|
9
6
|
CGFloat bottom = toBottom ? CGRectGetHeight(bounds) : CGRectGetHeight(bounds) - safeArea.bottom;
|
|
@@ -20,31 +17,32 @@ UIEdgeInsets ANNScreenInsetsOverRoot(CGRect rootFrame, CGSize viewSize, UIEdgeIn
|
|
|
20
17
|
|
|
21
18
|
UIEdgeInsets ANNScreenPadding(UIEdgeInsets insets, ANNNavigationOptions *options,
|
|
22
19
|
ANNScreenPaddingContext context) {
|
|
20
|
+
ANNTopBarOptions *topBar = options.topBar;
|
|
21
|
+
BOOL topBarShown = [topBar.visible withDefault:YES];
|
|
22
|
+
// Under a large title the list keeps its first rows clear of the bar itself. A padded top would follow the bar as
|
|
23
|
+
// it collapses and move the list with it, and UIKit, which collapses the title by the list's offset, would keep
|
|
24
|
+
// the small title hidden.
|
|
25
|
+
BOOL largeTitleShown = topBarShown && context.inStack && ANNLargeTitleCanShow(options);
|
|
23
26
|
NSArray<NSString *> *edges = options.layout.safeAreaEdges;
|
|
24
27
|
if (edges) {
|
|
25
|
-
// Exactly the edges given; unknown names count for nothing
|
|
26
|
-
|
|
28
|
+
// Exactly the edges given, but the top under a large title; unknown names count for nothing
|
|
29
|
+
// (`layout.safeAreaEdges`).
|
|
30
|
+
BOOL top = [edges containsObject:@"top"] && !largeTitleShown;
|
|
31
|
+
return UIEdgeInsetsMake(top ? insets.top : 0,
|
|
27
32
|
[edges containsObject:@"left"] ? insets.left : 0,
|
|
28
33
|
[edges containsObject:@"bottom"] ? insets.bottom : 0,
|
|
29
34
|
[edges containsObject:@"right"] ? insets.right : 0);
|
|
30
35
|
}
|
|
31
36
|
UIEdgeInsets padding = insets;
|
|
32
|
-
ANNTopBarOptions *topBar = options.topBar;
|
|
33
|
-
BOOL topBarShown = [topBar.visible withDefault:YES];
|
|
34
37
|
// A bar hidden for a while (`hideOnScroll`, `hideOnTap`, `hideOnKeyboard`) still counts as shown: only
|
|
35
38
|
// `topBar.visible: false` gives the content its top back. A large title that can show takes the top too: the list
|
|
36
39
|
// goes under the bar that collapses it.
|
|
37
|
-
if (topBarShown && context.inStack &&
|
|
38
|
-
(ANNScreenIsUnderTopBar(options) || ANNLargeTitleCanShow(options))) {
|
|
40
|
+
if (largeTitleShown || (topBarShown && context.inStack && ANNScreenIsUnderTopBar(options))) {
|
|
39
41
|
padding.top = 0;
|
|
40
42
|
}
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
if (insets.bottom > context.windowBottomSafeArea + ANNBottomBarThreshold ||
|
|
45
|
-
(context.inStack && context.stackShowsToolbar && [topBar.hideOnScroll withDefault:NO])) {
|
|
46
|
-
padding.bottom = 0;
|
|
47
|
-
}
|
|
43
|
+
// The bottom is free: the content goes down to the bottom of the screen, under the home indicator and under a bar
|
|
44
|
+
// at the bottom, and a list keeps its last rows clear with `useSafeAreaInsets()`.
|
|
45
|
+
padding.bottom = 0;
|
|
48
46
|
BOOL behindVerticalBar = [options.layout.drawBehindVerticalBar withDefault:YES] &&
|
|
49
47
|
[options.layout.verticalBars withDefault:YES];
|
|
50
48
|
if (behindVerticalBar) {
|