@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
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
#import "ANNBottomTabsAccessoryView.h"
|
|
4
4
|
#import "ANNBottomTabsController.h"
|
|
5
5
|
#import "ANNBottomTabsCustomRow.h"
|
|
6
|
+
#import "ANNOptionImages.h"
|
|
6
7
|
#import "ANNTabDotView.h"
|
|
7
8
|
#import "ANNTabsDesign.h"
|
|
8
9
|
#import "UITabBar+utils.h"
|
|
@@ -11,9 +12,6 @@
|
|
|
11
12
|
|
|
12
13
|
// The dot of a tab before iOS 26: its default size and color.
|
|
13
14
|
static const CGFloat ANNDotDefaultSize = 6;
|
|
14
|
-
// A button not there yet gets its `testID` again this often, at most this many times (`bottomTab.testID`).
|
|
15
|
-
static const NSTimeInterval ANNTestIDRetryInterval = 0.15;
|
|
16
|
-
static const NSUInteger ANNTestIDRetries = 5;
|
|
17
15
|
|
|
18
16
|
// A picture of `color` (both of its styles when it is dynamic): the bar's 1×1 background and the border's line.
|
|
19
17
|
static UIImage *ANNImageOfColor(UIColor *color, CGSize size) {
|
|
@@ -62,17 +60,29 @@ static id ANNValue(NSArray *list, NSUInteger index) {
|
|
|
62
60
|
NSMutableArray<NSNumber *> *_roleItems;
|
|
63
61
|
// The identifiers the buttons had before the core gave them a `testID`, to give back.
|
|
64
62
|
NSMapTable<UIView *, NSString *> *_buttonIds;
|
|
63
|
+
// What the `testID`s and the dots were last applied to: the bar's items, the button of each tab and of More, the
|
|
64
|
+
// bar's size and its traits. UIKit makes the buttons anew (rotation, text size, items moving between the bar and
|
|
65
|
+
// More), and a layout that finds other buttons applies them again.
|
|
66
|
+
NSPointerArray *_appliedButtons;
|
|
67
|
+
CGSize _appliedBarSize;
|
|
68
|
+
UITraitCollection *_appliedBarTraits;
|
|
65
69
|
BOOL _tabsAreSet;
|
|
66
70
|
BOOL _titlesHidden;
|
|
71
|
+
// A dot that shows was placed while its button had no window (the tabs under a full-screen modal): it hides then,
|
|
72
|
+
// and the next layout in the window places it, whatever the check of the buttons says.
|
|
73
|
+
BOOL _dotsWaitForWindow;
|
|
67
74
|
// The bar's look: its options, and the background and border every item's look starts from.
|
|
68
75
|
ANNBottomTabsOptions *_barOptions;
|
|
69
76
|
UITabBarAppearance *_base;
|
|
70
77
|
ANNBottomTabsCustomRow *_row;
|
|
71
|
-
// The accessory shown (its id), and the content view of each accessory made
|
|
78
|
+
// The accessory shown (its id), and the content view of each accessory made: kept while hidden, until another
|
|
79
|
+
// accessory shows or the tabs go.
|
|
72
80
|
NSString *_accessoryId;
|
|
73
81
|
NSMutableDictionary<NSString *, ANNBottomTabsAccessoryView *> *_accessoryViews;
|
|
74
82
|
// The pictures of the bar's colors by color and size.
|
|
75
83
|
NSMutableDictionary<NSArray *, UIImage *> *_colorImages;
|
|
84
|
+
// The icons an item waits for, by layout index: a token per wait, which a later build of the item replaces.
|
|
85
|
+
NSMutableDictionary<NSNumber *, NSObject *> *_iconLoads;
|
|
76
86
|
}
|
|
77
87
|
|
|
78
88
|
- (nullable ANNBottomTabsController *)tabs {
|
|
@@ -82,10 +92,20 @@ static id ANNValue(NSArray *list, NSUInteger index) {
|
|
|
82
92
|
}
|
|
83
93
|
|
|
84
94
|
+ (void)repaintNode:(UIViewController *)node {
|
|
95
|
+
[self repaintNode:node showingIn:node.viewIfLoaded];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Children first. Only what shows with the tab repaints: a node whose view is out of the tab's views (a stack's lower
|
|
99
|
+
// screens, a hidden tab of tabs inside) takes the new options at its own appearance, as the repaint of what shows
|
|
100
|
+
// leaves the nodes out of a window (`ANNOptionsRepaint`).
|
|
101
|
+
+ (void)repaintNode:(UIViewController *)node showingIn:(nullable UIView *)tabView {
|
|
85
102
|
for (UIViewController *child in node.layoutChildren) {
|
|
86
|
-
[self repaintNode:child];
|
|
103
|
+
[self repaintNode:child showingIn:tabView];
|
|
104
|
+
}
|
|
105
|
+
UIView *view = node.viewIfLoaded;
|
|
106
|
+
if (tabView && view && [view isDescendantOfView:tabView]) {
|
|
107
|
+
[node.presenter applyDefaultOptionsChange:[node resolveOptionsWithDefault]];
|
|
87
108
|
}
|
|
88
|
-
[node.presenter applyDefaultOptionsChange:[node resolveOptionsWithDefault]];
|
|
89
109
|
}
|
|
90
110
|
|
|
91
111
|
#pragma mark - Creation
|
|
@@ -110,8 +130,10 @@ static id ANNValue(NSArray *list, NSUInteger index) {
|
|
|
110
130
|
_dotViews = [NSMutableArray new];
|
|
111
131
|
_roleItems = [NSMutableArray new];
|
|
112
132
|
_buttonIds = [NSMapTable weakToStrongObjectsMapTable];
|
|
133
|
+
_appliedButtons = [NSPointerArray weakObjectsPointerArray];
|
|
113
134
|
_accessoryViews = [NSMutableDictionary new];
|
|
114
135
|
_colorImages = [NSMutableDictionary new];
|
|
136
|
+
_iconLoads = [NSMutableDictionary new];
|
|
115
137
|
for (NSUInteger index = 0; index < count; index++) {
|
|
116
138
|
[_badges addObject:NSNull.null];
|
|
117
139
|
[_dots addObject:[ANNBottomTabDotIndicatorOptions new]];
|
|
@@ -237,7 +259,7 @@ static id ANNValue(NSArray *list, NSUInteger index) {
|
|
|
237
259
|
[_row applyOptions:resolvedOptions.bottomTabs.customRow];
|
|
238
260
|
}
|
|
239
261
|
[self applyAccessoryOf:resolvedOptions animated:NO];
|
|
240
|
-
[self
|
|
262
|
+
[self applyButtonTestIDs];
|
|
241
263
|
}
|
|
242
264
|
|
|
243
265
|
#pragma mark - ANNNodePresenter
|
|
@@ -301,7 +323,7 @@ static id ANNValue(NSArray *list, NSUInteger index) {
|
|
|
301
323
|
}
|
|
302
324
|
[self buildItemAtIndex:index bottomTab:bottomTab updatesBadgeAndDot:badgeAndDot];
|
|
303
325
|
[self updateCells];
|
|
304
|
-
[self
|
|
326
|
+
[self applyButtonTestIDs];
|
|
305
327
|
}
|
|
306
328
|
|
|
307
329
|
// The whole item from `bottomTab`; the badge and the dot from it only with `updatesBadgeAndDot`.
|
|
@@ -326,8 +348,12 @@ static id ANNValue(NSArray *list, NSUInteger index) {
|
|
|
326
348
|
// The row's items show nothing: no image, no title, only the accessibility.
|
|
327
349
|
NSString *text = [ANNBottomTabItemBuilder titleOf:bottomTab];
|
|
328
350
|
NSString *title = row || _titlesHidden ? nil : text;
|
|
329
|
-
|
|
330
|
-
|
|
351
|
+
// While new icons load off the main queue the item keeps the ones it shows; a wait of an earlier build is over.
|
|
352
|
+
[_iconLoads removeObjectForKey:@(index)];
|
|
353
|
+
BOOL keepsIcons = !row && [self loadsIconsLaterOf:bottomTab atIndex:index];
|
|
354
|
+
UIImage *icon = row || keepsIcons ? nil : [ANNBottomTabItemBuilder iconOf:bottomTab];
|
|
355
|
+
UIImage *selectedIcon =
|
|
356
|
+
row || keepsIcons ? nil : [ANNBottomTabItemBuilder selectedIconOf:bottomTab];
|
|
331
357
|
if (@available(iOS 18.0, *)) {
|
|
332
358
|
if (uiTab) {
|
|
333
359
|
UITab *systemTab = uiTab;
|
|
@@ -339,12 +365,13 @@ static id ANNValue(NSArray *list, NSUInteger index) {
|
|
|
339
365
|
systemTab.title = tabTitle;
|
|
340
366
|
}
|
|
341
367
|
}
|
|
342
|
-
if ((!search || icon || row) && systemTab.image != icon) {
|
|
368
|
+
if (!keepsIcons && (!search || icon || row) && systemTab.image != icon) {
|
|
343
369
|
systemTab.image = icon;
|
|
344
370
|
}
|
|
345
371
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 270000
|
|
346
372
|
if (@available(iOS 26.1, *)) {
|
|
347
|
-
if ((!search || selectedIcon || row) &&
|
|
373
|
+
if (!keepsIcons && (!search || selectedIcon || row) &&
|
|
374
|
+
systemTab.selectedImage != selectedIcon) {
|
|
348
375
|
systemTab.selectedImage = selectedIcon;
|
|
349
376
|
}
|
|
350
377
|
}
|
|
@@ -365,7 +392,7 @@ static id ANNValue(NSArray *list, NSUInteger index) {
|
|
|
365
392
|
item.accessibilityLabel = text;
|
|
366
393
|
}
|
|
367
394
|
}
|
|
368
|
-
if (!roleItem || icon) {
|
|
395
|
+
if (!keepsIcons && (!roleItem || icon)) {
|
|
369
396
|
if (item.image != icon) {
|
|
370
397
|
item.image = icon;
|
|
371
398
|
}
|
|
@@ -427,6 +454,89 @@ static id ANNValue(NSArray *list, NSUInteger index) {
|
|
|
427
454
|
}
|
|
428
455
|
}
|
|
429
456
|
|
|
457
|
+
// `bottomTab` with the images that came in place of the rasters they came for: a build from it asks the cache for
|
|
458
|
+
// none of them. A raster that failed stays as it was (its failure answers for a moment).
|
|
459
|
+
static ANNBottomTabOptions *ANNWithIcons(ANNBottomTabOptions *bottomTab, NSArray<Image *> *rasters,
|
|
460
|
+
NSArray *came) {
|
|
461
|
+
ANNBottomTabOptions *built = [bottomTab copy];
|
|
462
|
+
for (NSUInteger place = 0; place < rasters.count; place++) {
|
|
463
|
+
UIImage *image = [came[place] isKindOfClass:UIImage.class] ? came[place] : nil;
|
|
464
|
+
if (!image) {
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
Image *raster = rasters[place];
|
|
468
|
+
if (raster == bottomTab.icon) {
|
|
469
|
+
built.icon = [[Image alloc] initWithValue:image];
|
|
470
|
+
}
|
|
471
|
+
if (raster == bottomTab.selectedIcon) {
|
|
472
|
+
built.selectedIcon = [[Image alloc] initWithValue:image];
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
return built;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// New raster icons of an item on the bar that shows load off the main queue when the cache doesn't have them: the item
|
|
479
|
+
// takes them when they came, built again from the same options with the images that came (the cache may have let them
|
|
480
|
+
// go by then: icons larger than it), unless it was built again first (the last build wins). The first icons, and every
|
|
481
|
+
// icon while the bar is out of a window, load at once: the tab's first frame shows them.
|
|
482
|
+
- (BOOL)loadsIconsLaterOf:(ANNBottomTabOptions *)bottomTab atIndex:(NSUInteger)index {
|
|
483
|
+
if (!_tabsAreSet || !self.tabs.viewIfLoaded.window) {
|
|
484
|
+
return NO;
|
|
485
|
+
}
|
|
486
|
+
NSArray<Image *> *rasters = [ANNBottomTabItemBuilder rastersOf:bottomTab];
|
|
487
|
+
BOOL later = NO;
|
|
488
|
+
for (Image *raster in rasters) {
|
|
489
|
+
if ([ANNOptionImages loadsLater:raster.source]) {
|
|
490
|
+
later = YES;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
if (!later) {
|
|
494
|
+
return NO;
|
|
495
|
+
}
|
|
496
|
+
NSObject *load = [NSObject new];
|
|
497
|
+
_iconLoads[@(index)] = load;
|
|
498
|
+
// Every raster of the item, those the cache has too: each comes with its image, by its place in `rasters`.
|
|
499
|
+
NSMutableArray *came = [NSMutableArray arrayWithCapacity:rasters.count];
|
|
500
|
+
for (NSUInteger each = 0; each < rasters.count; each++) {
|
|
501
|
+
[came addObject:NSNull.null];
|
|
502
|
+
}
|
|
503
|
+
__block NSUInteger pending = rasters.count;
|
|
504
|
+
__block BOOL asking = YES;
|
|
505
|
+
__weak ANNBottomTabsPresenter *weakSelf = self;
|
|
506
|
+
[rasters enumerateObjectsUsingBlock:^(Image *raster, NSUInteger place, BOOL *stop) {
|
|
507
|
+
[ANNOptionImages loadLater:raster.source
|
|
508
|
+
done:^(UIImage *image) {
|
|
509
|
+
if (image) {
|
|
510
|
+
came[place] = image;
|
|
511
|
+
}
|
|
512
|
+
pending--;
|
|
513
|
+
ANNBottomTabsPresenter *presenter = weakSelf;
|
|
514
|
+
if (pending == 0 && !asking) {
|
|
515
|
+
[presenter iconsCame:load
|
|
516
|
+
atIndex:index
|
|
517
|
+
bottomTab:ANNWithIcons(bottomTab, rasters, came)];
|
|
518
|
+
}
|
|
519
|
+
}];
|
|
520
|
+
}];
|
|
521
|
+
asking = NO;
|
|
522
|
+
if (pending == 0) {
|
|
523
|
+
// A load ended while the others were asked for: the cache has them all now.
|
|
524
|
+
[_iconLoads removeObjectForKey:@(index)];
|
|
525
|
+
return NO;
|
|
526
|
+
}
|
|
527
|
+
return YES;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
- (void)iconsCame:(NSObject *)load
|
|
531
|
+
atIndex:(NSUInteger)index
|
|
532
|
+
bottomTab:(ANNBottomTabOptions *)bottomTab {
|
|
533
|
+
if (_iconLoads[@(index)] != load || index >= self.tabs.layoutTabs.count) {
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
[_iconLoads removeObjectForKey:@(index)];
|
|
537
|
+
[self buildItemAtIndex:index bottomTab:bottomTab updatesBadgeAndDot:NO];
|
|
538
|
+
}
|
|
539
|
+
|
|
430
540
|
- (void)updateDotAtIndex:(NSUInteger)index
|
|
431
541
|
shown:(BOOL)shown
|
|
432
542
|
options:(ANNBottomTabDotIndicatorOptions *)dot {
|
|
@@ -487,6 +597,7 @@ static id ANNValue(NSArray *list, NSUInteger index) {
|
|
|
487
597
|
if (anyDot) {
|
|
488
598
|
[bar layoutIfNeeded];
|
|
489
599
|
}
|
|
600
|
+
BOOL waitsForWindow = NO;
|
|
490
601
|
for (NSUInteger index = 0; index < tabs.layoutTabs.count; index++) {
|
|
491
602
|
ANNTabDotView *view = ANNValue(_dotViews, index);
|
|
492
603
|
if (!view) {
|
|
@@ -500,49 +611,36 @@ static id ANNValue(NSArray *list, NSUInteger index) {
|
|
|
500
611
|
}
|
|
501
612
|
UITabBarItem *item = tabs.layoutTabs[index].tabBarItem;
|
|
502
613
|
BOOL inBar = [bar.items indexOfObjectIdenticalTo:item] != NSNotFound;
|
|
503
|
-
|
|
614
|
+
UIView *button = inBar ? [bar viewOfItem:item] : nil;
|
|
615
|
+
waitsForWindow = waitsForWindow || (inBar && !button.window);
|
|
616
|
+
[view placeOverButton:button inBar:bar];
|
|
504
617
|
}
|
|
618
|
+
_dotsWaitForWindow = waitsForWindow;
|
|
505
619
|
}
|
|
506
620
|
|
|
507
621
|
#pragma mark - testID (`bottomTab.testID`, `bottomTabs.moreTestID`)
|
|
508
622
|
|
|
509
|
-
// Each tab's button carries its `testID`; a
|
|
510
|
-
//
|
|
511
|
-
- (void)
|
|
623
|
+
// Each tab's button carries its `testID`; a removed `testID` gives the button its identifier back. A button not
|
|
624
|
+
// there yet gets it at the layout that finds it (`tabsDidLayOut`).
|
|
625
|
+
- (void)applyButtonTestIDs {
|
|
512
626
|
ANNBottomTabsController *tabs = self.tabs;
|
|
513
627
|
UITabBar *bar = tabs.tabBar;
|
|
514
628
|
if (!tabs || !bar) {
|
|
515
629
|
return;
|
|
516
630
|
}
|
|
517
|
-
BOOL missing = NO;
|
|
518
631
|
for (NSUInteger index = 0; index < tabs.layoutTabs.count; index++) {
|
|
519
632
|
UITabBarItem *item = tabs.layoutTabs[index].tabBarItem;
|
|
520
|
-
NSString *testID = item.accessibilityIdentifier;
|
|
521
633
|
UIView *button = [bar viewOfItem:item];
|
|
522
|
-
if (
|
|
523
|
-
|
|
524
|
-
continue;
|
|
634
|
+
if (button) {
|
|
635
|
+
[self setTestID:item.accessibilityIdentifier ofButton:button];
|
|
525
636
|
}
|
|
526
|
-
[self setTestID:testID ofButton:button];
|
|
527
637
|
}
|
|
528
638
|
if (tabs.layoutTabs.count > 5) {
|
|
529
|
-
NSString *moreTestID = [_barOptions.moreTestID withDefault:nil];
|
|
530
639
|
UIView *button = [bar viewOfItem:tabs.moreNavigationController.tabBarItem];
|
|
531
640
|
if (button) {
|
|
532
|
-
[self setTestID:moreTestID ofButton:button];
|
|
533
|
-
} else {
|
|
534
|
-
missing = missing || moreTestID.length > 0;
|
|
641
|
+
[self setTestID:[_barOptions.moreTestID withDefault:nil] ofButton:button];
|
|
535
642
|
}
|
|
536
643
|
}
|
|
537
|
-
if (!missing || retries == 0) {
|
|
538
|
-
return;
|
|
539
|
-
}
|
|
540
|
-
__weak ANNBottomTabsPresenter *weakSelf = self;
|
|
541
|
-
dispatch_after(
|
|
542
|
-
dispatch_time(DISPATCH_TIME_NOW, (int64_t)(ANNTestIDRetryInterval * NSEC_PER_SEC)),
|
|
543
|
-
dispatch_get_main_queue(), ^{
|
|
544
|
-
[weakSelf applyButtonTestIDsWithRetries:retries - 1];
|
|
545
|
-
});
|
|
546
644
|
}
|
|
547
645
|
|
|
548
646
|
- (void)setTestID:(NSString *)testID ofButton:(UIView *)button {
|
|
@@ -626,8 +724,9 @@ static id ANNValue(NSArray *list, NSUInteger index) {
|
|
|
626
724
|
warned = YES;
|
|
627
725
|
RCTLogWarn(
|
|
628
726
|
@"[ApexNavigation] bottomTabs.backgroundColor is ignored with Liquid "
|
|
629
|
-
@"Glass (iOS 26). It applies
|
|
630
|
-
@"earlier iOS
|
|
727
|
+
@"Glass (iOS 26). It applies before iOS 26 and where UIKit keeps the "
|
|
728
|
+
@"earlier design for UIDesignRequiresCompatibility (iOS 26; iOS 27 only "
|
|
729
|
+
@"for an app built with an SDK before iOS 27).");
|
|
631
730
|
}
|
|
632
731
|
}
|
|
633
732
|
}
|
|
@@ -867,14 +966,15 @@ static id ANNValue(NSArray *list, NSUInteger index) {
|
|
|
867
966
|
[tabs updateRootLayoutOfShownScreens];
|
|
868
967
|
}
|
|
869
968
|
if (mergeOptions.testID.hasValue || mergeOptions.moreTestID.hasValue) {
|
|
870
|
-
[self
|
|
969
|
+
[self applyButtonTestIDs];
|
|
871
970
|
}
|
|
872
971
|
}
|
|
873
972
|
|
|
874
973
|
#pragma mark - The accessory (iOS 26)
|
|
875
974
|
|
|
876
|
-
// No name or `visible: false`: no accessory. The same id shown: nothing; another: a new one. A
|
|
877
|
-
//
|
|
975
|
+
// No name or `visible: false`: no accessory. The same id shown: nothing; another: a new one. A hidden accessory keeps
|
|
976
|
+
// its root, so one hidden and shown again keeps its state; the roots of the other ids stop once another accessory
|
|
977
|
+
// shows and theirs is out of the window.
|
|
878
978
|
- (void)applyAccessoryOf:(ANNNavigationOptions *)options animated:(BOOL)animated {
|
|
879
979
|
if (@available(iOS 26.0, *)) {
|
|
880
980
|
ANNBottomTabsController *tabs = self.tabs;
|
|
@@ -910,8 +1010,37 @@ static id ANNValue(NSArray *list, NSUInteger index) {
|
|
|
910
1010
|
return;
|
|
911
1011
|
}
|
|
912
1012
|
_accessoryId = componentId;
|
|
1013
|
+
[view whenOutOfWindow:nil];
|
|
913
1014
|
UITabAccessory *tabAccessory = [[UITabAccessory alloc] initWithContentView:view];
|
|
914
1015
|
[tabs setBottomAccessory:tabAccessory animated:animated && inWindow];
|
|
1016
|
+
[self stopAccessoriesOtherThan:componentId];
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
// The roots of the accessories not shown stop, each once its view is out of the window, unless it shows again first.
|
|
1021
|
+
- (void)stopAccessoriesOtherThan:(NSString *)shownId {
|
|
1022
|
+
ANNBottomTabsController *tabs = self.tabs;
|
|
1023
|
+
__weak ANNBottomTabsPresenter *weakSelf = self;
|
|
1024
|
+
__weak ANNReactComponentRegistry *weakComponents = tabs.components;
|
|
1025
|
+
for (NSString *componentId in _accessoryViews.allKeys) {
|
|
1026
|
+
if ([componentId isEqualToString:shownId]) {
|
|
1027
|
+
continue;
|
|
1028
|
+
}
|
|
1029
|
+
ANNBottomTabsAccessoryView *view = _accessoryViews[componentId];
|
|
1030
|
+
__weak ANNBottomTabsAccessoryView *weakView = view;
|
|
1031
|
+
[view whenOutOfWindow:^{
|
|
1032
|
+
ANNBottomTabsPresenter *presenter = weakSelf;
|
|
1033
|
+
ANNBottomTabsAccessoryView *gone = weakView;
|
|
1034
|
+
if (!presenter || !gone || presenter->_accessoryViews[componentId] != gone ||
|
|
1035
|
+
[presenter->_accessoryId isEqualToString:componentId]) {
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
[presenter->_accessoryViews removeObjectForKey:componentId];
|
|
1039
|
+
ANNReactComponentRegistry *components = weakComponents;
|
|
1040
|
+
if ([components existingComponent:componentId] == gone.reactView) {
|
|
1041
|
+
[components removeChildComponent:componentId];
|
|
1042
|
+
}
|
|
1043
|
+
}];
|
|
915
1044
|
}
|
|
916
1045
|
}
|
|
917
1046
|
|
|
@@ -960,18 +1089,78 @@ static id ANNValue(NSArray *list, NSUInteger index) {
|
|
|
960
1089
|
[self updateCells];
|
|
961
1090
|
}
|
|
962
1091
|
|
|
1092
|
+
// The `testID`s and the dots go on the buttons again only when the bar has other buttons than they were applied to,
|
|
1093
|
+
// another size or other traits; a merge and a rebuilt item apply them at once. A dot placed out of the window waits
|
|
1094
|
+
// for the next layout.
|
|
963
1095
|
- (void)tabsDidLayOut {
|
|
964
1096
|
if (!_tabsAreSet) {
|
|
965
1097
|
return;
|
|
966
1098
|
}
|
|
967
1099
|
[self updateHiddenTitles];
|
|
968
|
-
|
|
1100
|
+
BOOL changed = [self barChangedSinceApplied];
|
|
1101
|
+
if ((changed || _dotsWaitForWindow) && !ANNTabsDesign.isGlass) {
|
|
969
1102
|
[self placeDots];
|
|
970
1103
|
}
|
|
971
|
-
|
|
1104
|
+
if (changed) {
|
|
1105
|
+
[self applyButtonTestIDs];
|
|
1106
|
+
}
|
|
972
1107
|
[_row layOutInTabs];
|
|
973
1108
|
}
|
|
974
1109
|
|
|
1110
|
+
- (void)tabsDidAppear {
|
|
1111
|
+
if (_tabsAreSet && _dotsWaitForWindow && !ANNTabsDesign.isGlass) {
|
|
1112
|
+
[self placeDots];
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
// The bar's items and the button of each tab and of More, by pointer, against those last seen; no walk through the
|
|
1117
|
+
// buttons. An item moving between the bar and More changes the items. The tabs lay out before the bar does: a tab in
|
|
1118
|
+
// the bar without its button yet makes the bar lay out first.
|
|
1119
|
+
- (BOOL)barChangedSinceApplied {
|
|
1120
|
+
ANNBottomTabsController *tabs = self.tabs;
|
|
1121
|
+
UITabBar *bar = tabs.tabBar;
|
|
1122
|
+
if (!tabs || !bar) {
|
|
1123
|
+
return NO;
|
|
1124
|
+
}
|
|
1125
|
+
NSArray<UIViewController *> *layoutTabs = tabs.layoutTabs;
|
|
1126
|
+
NSArray<UITabBarItem *> *barItems = bar.items;
|
|
1127
|
+
NSUInteger tabCount = layoutTabs.count + (layoutTabs.count > 5 ? 1 : 0);
|
|
1128
|
+
NSMutableArray *seen = [NSMutableArray arrayWithArray:barItems];
|
|
1129
|
+
BOOL laidOut = NO;
|
|
1130
|
+
for (NSUInteger index = 0; index < tabCount; index++) {
|
|
1131
|
+
UITabBarItem *item = index < layoutTabs.count ? layoutTabs[index].tabBarItem
|
|
1132
|
+
: tabs.moreNavigationController.tabBarItem;
|
|
1133
|
+
UIView *button = [bar viewOfItem:item];
|
|
1134
|
+
if (!button && !laidOut && bar.window &&
|
|
1135
|
+
[barItems indexOfObjectIdenticalTo:item] != NSNotFound) {
|
|
1136
|
+
laidOut = YES;
|
|
1137
|
+
[bar layoutIfNeeded];
|
|
1138
|
+
button = [bar viewOfItem:item];
|
|
1139
|
+
}
|
|
1140
|
+
[seen addObject:button ?: NSNull.null];
|
|
1141
|
+
}
|
|
1142
|
+
NSUInteger count = seen.count;
|
|
1143
|
+
BOOL changed = _appliedButtons.count != count;
|
|
1144
|
+
for (NSUInteger index = 0; index < count && !changed; index++) {
|
|
1145
|
+
id object = seen[index] == NSNull.null ? nil : seen[index];
|
|
1146
|
+
changed = (__bridge void *)object != [_appliedButtons pointerAtIndex:index];
|
|
1147
|
+
}
|
|
1148
|
+
CGSize size = bar.bounds.size;
|
|
1149
|
+
UITraitCollection *traits = bar.traitCollection;
|
|
1150
|
+
changed = changed || !CGSizeEqualToSize(size, _appliedBarSize) ||
|
|
1151
|
+
![traits isEqual:_appliedBarTraits];
|
|
1152
|
+
if (!changed) {
|
|
1153
|
+
return NO;
|
|
1154
|
+
}
|
|
1155
|
+
_appliedButtons.count = 0;
|
|
1156
|
+
for (id object in seen) {
|
|
1157
|
+
[_appliedButtons addPointer:object == NSNull.null ? NULL : (__bridge void *)object];
|
|
1158
|
+
}
|
|
1159
|
+
_appliedBarSize = size;
|
|
1160
|
+
_appliedBarTraits = traits;
|
|
1161
|
+
return YES;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
975
1164
|
// The glass bar measures a title when it is set and keeps that size: a title set before the bar was ever in a window
|
|
976
1165
|
// was measured in a button of its first layout there, when the bar's floating platter had no size yet, and stays cut
|
|
977
1166
|
// short ("Sec…") and lower than a title measured later. Neither a layout of the bar nor of its buttons measures it
|
|
@@ -2,16 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
NS_ASSUME_NONNULL_BEGIN
|
|
4
4
|
|
|
5
|
-
/// Which design UIKit draws the bars in: the Liquid Glass of iOS 26, or the design before it, which
|
|
6
|
-
/// the app's Info.plist has `UIDesignRequiresCompatibility = YES` (the compatibility mode)
|
|
7
|
-
///
|
|
8
|
-
///
|
|
5
|
+
/// Which design UIKit draws the bars in: the Liquid Glass of iOS 26, or the design before it, which UIKit keeps when
|
|
6
|
+
/// the app's Info.plist has `UIDesignRequiresCompatibility = YES` (the compatibility mode): on iOS 26, and on iOS 27
|
|
7
|
+
/// only for an app built with an SDK before iOS 27. The key is read once per process. Every place of the core that
|
|
8
|
+
/// depends on the design asks here.
|
|
9
9
|
@interface ANNTabsDesign : NSObject
|
|
10
10
|
|
|
11
11
|
/// iOS 26 or later, and not the compatibility mode.
|
|
12
12
|
@property(class, nonatomic, readonly) BOOL isGlass;
|
|
13
13
|
|
|
14
|
-
/// iOS 26 or later with `UIDesignRequiresCompatibility = YES
|
|
14
|
+
/// iOS 26 or later with `UIDesignRequiresCompatibility = YES`, where UIKit honors it (not on iOS 27 and later for an
|
|
15
|
+
/// app built with the iOS 27 SDK): the bars look as before iOS 26.
|
|
15
16
|
@property(class, nonatomic, readonly) BOOL isCompatibilityMode;
|
|
16
17
|
|
|
17
18
|
/// iOS 18 and later on an iPad or a Mac in a regular width: the system's tab bar is on top (or in the sidebar), and
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
@implementation ANNTabsDesign
|
|
4
4
|
|
|
5
|
-
// Read once: the Info.plist of a running app doesn't change.
|
|
5
|
+
// Read once: the Info.plist of a running app doesn't change. iOS 26 keeps the earlier design for the key; iOS 27 keeps
|
|
6
|
+
// it only for an app built with an SDK before iOS 27 and ignores it for one built with the iOS 27 SDK (an app linked
|
|
7
|
+
// against the iOS 26 SDK keeps the earlier design on iOS 27, one linked against the iOS 27 SDK gets the glass). The
|
|
8
|
+
// core is compiled with the app, so the SDK it is compiled with is the app's.
|
|
6
9
|
+ (BOOL)isCompatibilityMode {
|
|
7
10
|
static BOOL compatibility;
|
|
8
11
|
static dispatch_once_t once;
|
|
@@ -11,6 +14,11 @@
|
|
|
11
14
|
id value = NSBundle.mainBundle.infoDictionary[@"UIDesignRequiresCompatibility"];
|
|
12
15
|
compatibility = [value respondsToSelector:@selector(boolValue)] && [value boolValue];
|
|
13
16
|
}
|
|
17
|
+
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 270000
|
|
18
|
+
if (@available(iOS 27.0, *)) {
|
|
19
|
+
compatibility = NO;
|
|
20
|
+
}
|
|
21
|
+
#endif
|
|
14
22
|
});
|
|
15
23
|
return compatibility;
|
|
16
24
|
}
|
|
@@ -4,18 +4,18 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* The button of an item in the tab bar. UIKit has no public API for it: this reads the private
|
|
7
|
-
* `view` of the item,
|
|
7
|
+
* `view` of the item, the core's one private read of the bar, and is nil when the item has no
|
|
8
|
+
* button (out of the bar, or before its layout). When UIKit has no such key any more, DEBUG logs it
|
|
9
|
+
* once.
|
|
8
10
|
*/
|
|
9
11
|
- (UIView *)viewOfItem:(UITabBarItem *)item;
|
|
10
12
|
|
|
11
|
-
- (UIView *)tabBarItemViewAtIndex:(NSUInteger)index;
|
|
12
|
-
|
|
13
13
|
- (void)removeTabBarItemTitles;
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Icons in the middle of the buttons of this tab bar, for items without titles: before iOS 26 (and
|
|
17
|
-
* in its compatibility mode) a button keeps the room of its title; the iOS 26
|
|
18
|
-
* icons itself, and this does nothing there. UIKit has no public API for it: the layout of the
|
|
17
|
+
* in its compatibility mode, `ANNTabsDesign`) a button keeps the room of its title; the iOS 26
|
|
18
|
+
* design centers the icons itself, and this does nothing there. UIKit has no public API for it: the layout of the
|
|
19
19
|
* private button class changes once for the app, and only tab bars with centered images move their
|
|
20
20
|
* icons (and badges). `NO` gives the buttons the layout of UIKit back.
|
|
21
21
|
*/
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
#import "UITabBar+utils.h"
|
|
2
|
+
#import "ANNTabsDesign.h"
|
|
2
3
|
#import "UIView+Utils.h"
|
|
4
|
+
#import <React/RCTLog.h>
|
|
3
5
|
#import <objc/runtime.h>
|
|
4
6
|
|
|
5
7
|
static const void *ANNItemImagesCenteredKey = &ANNItemImagesCenteredKey;
|
|
@@ -37,17 +39,16 @@ static void ANNTabBarButtonLayoutSubviews(UIView *button, SEL _cmd) {
|
|
|
37
39
|
badge.center = CGPointMake(badge.center.x, badge.center.y + offset);
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
// The design of iOS 26 centers the icon of an item without a title itself;
|
|
41
|
-
//
|
|
42
|
+
// The design of iOS 26 centers the icon of an item without a title itself; the design before it
|
|
43
|
+
// (before iOS 26, and the compatibility mode where UIKit keeps it) keeps the title's room.
|
|
42
44
|
static BOOL ANNTabBarButtonsKeepTitleRoom(void) {
|
|
43
|
-
|
|
44
|
-
return [[NSBundle.mainBundle objectForInfoDictionaryKey:@"UIDesignRequiresCompatibility"]
|
|
45
|
-
boolValue];
|
|
46
|
-
}
|
|
47
|
-
return YES;
|
|
45
|
+
return !ANNTabsDesign.isGlass;
|
|
48
46
|
}
|
|
49
47
|
|
|
50
|
-
// Once for the app; the buttons of other tab bars keep the layout of UIKit.
|
|
48
|
+
// Once for the app; the buttons of other tab bars keep the layout of UIKit. No public API does this: in the
|
|
49
|
+
// compatibility mode of iOS 26 UIKit ignores `imageInsets` and a symbol's baseline offset, and a symbol drawn into a
|
|
50
|
+
// taller bitmap is scaled down and stops being a symbol. `badgePositionAdjustment` would move the badge alone, so the
|
|
51
|
+
// button's layout moves both.
|
|
51
52
|
static void ANNInstallTabBarButtonLayout(void) {
|
|
52
53
|
static dispatch_once_t once;
|
|
53
54
|
dispatch_once(&once, ^{
|
|
@@ -65,18 +66,36 @@ static void ANNInstallTabBarButtonLayout(void) {
|
|
|
65
66
|
});
|
|
66
67
|
}
|
|
67
68
|
|
|
69
|
+
// Once per app run, in DEBUG: the tab items' buttons can't be found any more.
|
|
70
|
+
static void ANNWarnNoButtonOfItem(void) {
|
|
71
|
+
#if DEBUG
|
|
72
|
+
static dispatch_once_t once;
|
|
73
|
+
dispatch_once(&once, ^{
|
|
74
|
+
RCTLogWarn(@"[ApexNavigation] This iOS version gives no button for a tab item: "
|
|
75
|
+
@"bottomTab.testID on the tab buttons, the dot before iOS 26 and the long "
|
|
76
|
+
@"press on a tab don't apply.");
|
|
77
|
+
});
|
|
78
|
+
#endif
|
|
79
|
+
}
|
|
80
|
+
|
|
68
81
|
@implementation UITabBar (utils)
|
|
69
82
|
|
|
70
83
|
- (UIView *)viewOfItem:(UITabBarItem *)item {
|
|
84
|
+
if (!item) {
|
|
85
|
+
return nil;
|
|
86
|
+
}
|
|
87
|
+
// An item out of the bar (in More, or before the bar's first layout) has no button: that is no failure. Only an
|
|
88
|
+
// item without the `view` key, or with something else under it, says that UIKit changed.
|
|
71
89
|
if (![item respondsToSelector:NSSelectorFromString(@"view")]) {
|
|
90
|
+
ANNWarnNoButtonOfItem();
|
|
72
91
|
return nil;
|
|
73
92
|
}
|
|
74
93
|
id view = [item valueForKey:@"view"];
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return
|
|
94
|
+
if (view && ![view isKindOfClass:UIView.class]) {
|
|
95
|
+
ANNWarnNoButtonOfItem();
|
|
96
|
+
return nil;
|
|
97
|
+
}
|
|
98
|
+
return view;
|
|
80
99
|
}
|
|
81
100
|
|
|
82
101
|
- (void)removeTabBarItemTitles {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
#import "ANNOptions.h"
|
|
4
4
|
#import "ANNSetStackRootAnimationOptions.h"
|
|
5
5
|
#import "ANNStackAnimationOptions.h"
|
|
6
|
+
#import "ANNStackPopAnimationOptions.h"
|
|
6
7
|
#import "ANNStackPushAnimationOptions.h"
|
|
7
8
|
|
|
8
9
|
NS_ASSUME_NONNULL_BEGIN
|
|
@@ -11,7 +12,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
11
12
|
@interface ANNAnimationOptions : ANNOptions
|
|
12
13
|
|
|
13
14
|
@property(nonatomic, strong) ANNStackPushAnimationOptions *push;
|
|
14
|
-
@property(nonatomic, strong)
|
|
15
|
+
@property(nonatomic, strong) ANNStackPopAnimationOptions *pop;
|
|
15
16
|
@property(nonatomic, strong) ANNSetStackRootAnimationOptions *setStackRoot;
|
|
16
17
|
@property(nonatomic, strong) ANNEnterExitScreenAnimationOptions *setRoot;
|
|
17
18
|
@property(nonatomic, strong) ANNModalAnimationOptions *showModal;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
+ (NSArray<ANNOptionField *> *)optionFields {
|
|
6
6
|
return @[
|
|
7
7
|
[ANNOptionField groupField:@"push" class:ANNStackPushAnimationOptions.class],
|
|
8
|
-
[ANNOptionField groupField:@"pop" class:
|
|
8
|
+
[ANNOptionField groupField:@"pop" class:ANNStackPopAnimationOptions.class],
|
|
9
9
|
[ANNOptionField groupField:@"setStackRoot" class:ANNSetStackRootAnimationOptions.class],
|
|
10
10
|
[ANNOptionField groupField:@"setRoot" class:ANNEnterExitScreenAnimationOptions.class],
|
|
11
11
|
[ANNOptionField groupField:@"showModal" class:ANNModalAnimationOptions.class],
|
|
@@ -11,6 +11,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
11
11
|
|
|
12
12
|
@property(nonatomic, strong) Bool *visible;
|
|
13
13
|
@property(nonatomic, strong) Bool *animate;
|
|
14
|
+
/// `'platform'` or `'none'`; read on Android only: the system switches tabs at once.
|
|
15
|
+
@property(nonatomic, strong) Text *switchAnimation;
|
|
14
16
|
/// The index of the tab to select; a whole number (the fraction is dropped).
|
|
15
17
|
@property(nonatomic, strong) Double *currentTabIndex;
|
|
16
18
|
@property(nonatomic, strong) Text *currentTabId;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
return @[
|
|
7
7
|
[ANNOptionField boolField:@"visible"],
|
|
8
8
|
[ANNOptionField boolField:@"animate"],
|
|
9
|
+
[ANNOptionField enumField:@"switchAnimation" values:@[ @"platform", @"none" ]],
|
|
9
10
|
[ANNOptionField doubleField:@"currentTabIndex"],
|
|
10
11
|
[ANNOptionField textField:@"currentTabId"],
|
|
11
12
|
[ANNOptionField textField:@"testID"],
|