@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
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
#import "ANNBarButtonComponentView.h"
|
|
3
3
|
#import "ANNIconButtonImage.h"
|
|
4
4
|
#import "ANNShowTextButton.h"
|
|
5
|
+
#import "ANNTabsDesign.h"
|
|
5
6
|
#import "ANNUIBarButtonItem.h"
|
|
7
|
+
#import "ANNUserChoice.h"
|
|
6
8
|
#import "UIViewController+LayoutProtocol.h"
|
|
7
9
|
#import <React/RCTLog.h>
|
|
8
10
|
|
|
@@ -54,6 +56,187 @@ static void ANNSetButtonsOfSide(ANNNavigationOptions *options, ANNBarButtonsSide
|
|
|
54
56
|
}
|
|
55
57
|
}
|
|
56
58
|
|
|
59
|
+
static ANNButtonOptions *ANNButtonWithId(NSArray<ANNButtonOptions *> *buttons, NSString *buttonId) {
|
|
60
|
+
for (ANNButtonOptions *button in buttons) {
|
|
61
|
+
if ([[button.identifier withDefault:nil] isEqualToString:buttonId]) {
|
|
62
|
+
return button;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return nil;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// The button `buttonId` of `side` in `options` changed on a copy, in a new list; nothing when the side has no such
|
|
69
|
+
// button. The other buttons stay the objects they are: nothing changes them.
|
|
70
|
+
static void ANNChangeButton(ANNNavigationOptions *options,
|
|
71
|
+
ANNBarButtonsSide side,
|
|
72
|
+
NSString *buttonId,
|
|
73
|
+
void (^change)(ANNButtonOptions *changed)) {
|
|
74
|
+
NSArray<ANNButtonOptions *> *list = ANNButtonsOfSide(options, side);
|
|
75
|
+
if (!ANNButtonWithId(list, buttonId)) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
NSMutableArray<ANNButtonOptions *> *changedList = [NSMutableArray arrayWithCapacity:list.count];
|
|
79
|
+
for (ANNButtonOptions *button in list) {
|
|
80
|
+
if ([[button.identifier withDefault:nil] isEqualToString:buttonId]) {
|
|
81
|
+
ANNButtonOptions *copy = [button copy];
|
|
82
|
+
change(copy);
|
|
83
|
+
[changedList addObject:copy];
|
|
84
|
+
} else {
|
|
85
|
+
[changedList addObject:button];
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
ANNSetButtonsOfSide(options, side, changedList);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
#pragma mark - The user's choices
|
|
92
|
+
|
|
93
|
+
static NSString *ANNToggleChoiceKey(ANNBarButtonsSide side, NSString *buttonId) {
|
|
94
|
+
return [NSString stringWithFormat:@"buttons.%ld.selected.%@", (long)side, buttonId];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
static NSString *ANNButtonMenuChoiceKey(ANNBarButtonsSide side, NSString *buttonId) {
|
|
98
|
+
return [NSString stringWithFormat:@"buttons.%ld.menu.%@", (long)side, buttonId];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// The button `buttonId` of `side` in `options`, or nil.
|
|
102
|
+
static ANNButtonOptions *ANNButtonIn(ANNNavigationOptions *options, ANNBarButtonsSide side,
|
|
103
|
+
NSString *buttonId) {
|
|
104
|
+
return ANNButtonWithId(ANNButtonsOfSide(options, side), buttonId);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// A toggle the user flipped: `selected` of the button with its id, wherever its list comes from. It goes when the
|
|
108
|
+
// node's resolution after a merge has no such button, or when the merge gives the button a `selected` other than the
|
|
109
|
+
// app had (the own button's, else the button the node resolved to before the merge), by the rules of a menu's check.
|
|
110
|
+
static ANNUserChoice *ANNToggleChoice(ANNBarButtonsSide side, NSString *buttonId, BOOL selected) {
|
|
111
|
+
return [ANNUserChoice choiceWithValue:@(selected)
|
|
112
|
+
apply:^(ANNNavigationOptions *options, id value) {
|
|
113
|
+
BOOL on = [(NSNumber *)value boolValue];
|
|
114
|
+
ANNChangeButton(options, side, buttonId, ^(ANNButtonOptions *changed) {
|
|
115
|
+
changed.selected = [Bool withValue:on];
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
merged:^id(id value, ANNNavigationOptions *merge, ANNNavigationOptions *own,
|
|
119
|
+
ANNNavigationOptions *before, ANNNavigationOptions *after) {
|
|
120
|
+
if (!ANNButtonIn(after, side, buttonId)) {
|
|
121
|
+
return nil;
|
|
122
|
+
}
|
|
123
|
+
ANNButtonOptions *given = ANNButtonIn(merge, side, buttonId);
|
|
124
|
+
if (!given.selected.hasValue) {
|
|
125
|
+
return value;
|
|
126
|
+
}
|
|
127
|
+
ANNButtonOptions *was = ANNButtonIn(own, side, buttonId);
|
|
128
|
+
if (!was.selected.hasValue) {
|
|
129
|
+
was = ANNButtonIn(before, side, buttonId);
|
|
130
|
+
}
|
|
131
|
+
BOOL same = [given.selected withDefault:NO] == [was.selected withDefault:NO];
|
|
132
|
+
return same ? value : nil;
|
|
133
|
+
}];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// The items of the level (a menu's or a submenu's own list, without its submenus) that holds `itemId`, at any depth;
|
|
137
|
+
// nil when no level holds it.
|
|
138
|
+
static NSArray<ANNMenuItemOptions *> *ANNLevelOf(NSArray<ANNMenuItemOptions *> *items,
|
|
139
|
+
NSString *itemId) {
|
|
140
|
+
NSMutableArray<ANNMenuItemOptions *> *level = [NSMutableArray new];
|
|
141
|
+
BOOL holds = NO;
|
|
142
|
+
for (ANNMenuItemOptions *item in items) {
|
|
143
|
+
NSString *leafId = item.items.count ? nil : [item.identifier withDefault:nil];
|
|
144
|
+
if (leafId) {
|
|
145
|
+
[level addObject:item];
|
|
146
|
+
holds = holds || [leafId isEqualToString:itemId];
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (holds) {
|
|
150
|
+
return level;
|
|
151
|
+
}
|
|
152
|
+
for (ANNMenuItemOptions *item in items) {
|
|
153
|
+
if (item.items.count) {
|
|
154
|
+
NSArray<ANNMenuItemOptions *> *found = ANNLevelOf(item.items, itemId);
|
|
155
|
+
if (found) {
|
|
156
|
+
return found;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return nil;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// The ids of the items in the level that holds `itemId`: the neighbors one pick unchecks.
|
|
164
|
+
static NSArray<NSString *> *ANNNeighborsOf(NSArray<ANNMenuItemOptions *> *items, NSString *itemId) {
|
|
165
|
+
NSMutableArray<NSString *> *ids = [NSMutableArray new];
|
|
166
|
+
for (ANNMenuItemOptions *item in ANNLevelOf(items, itemId)) {
|
|
167
|
+
[ids addObject:[item.identifier withDefault:@""]];
|
|
168
|
+
}
|
|
169
|
+
return ids;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// The checked items of the level that holds `itemId` in `menu`: the field a merge gives that level. Nil when `menu`
|
|
173
|
+
// doesn't hold the item.
|
|
174
|
+
static NSSet<NSString *> *ANNCheckedInLevel(ANNMenuOptions *menu, NSString *itemId) {
|
|
175
|
+
NSArray<ANNMenuItemOptions *> *level = menu ? ANNLevelOf(menu.items, itemId) : nil;
|
|
176
|
+
if (!level) {
|
|
177
|
+
return nil;
|
|
178
|
+
}
|
|
179
|
+
NSMutableSet<NSString *> *checked = [NSMutableSet new];
|
|
180
|
+
for (ANNMenuItemOptions *item in level) {
|
|
181
|
+
if ([item.checked withDefault:NO]) {
|
|
182
|
+
[checked addObject:[item.identifier withDefault:@""]];
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return checked;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// A menu that has items, or nil: a merge without items gives no menu.
|
|
189
|
+
static ANNMenuOptions *ANNMenuWithItems(ANNMenuOptions *menu) {
|
|
190
|
+
return menu.items ? menu : nil;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// The picks of single-selection levels in one menu, in the order made: the resolution plays them again on a copy of
|
|
194
|
+
// the menu it has, so a new menu from the app keeps the check where its items have the same ids. As on Android
|
|
195
|
+
// (`UserChoices.yieldTo`), at each merge into the node a pick goes when the node's resolution after it no longer has
|
|
196
|
+
// the item, or when the merge gives the menu with other checks in the pick's level than the app had there (the own
|
|
197
|
+
// options' menu, else the menu the node resolved to before the merge); the picks of the other levels stay.
|
|
198
|
+
typedef ANNMenuOptions *_Nullable (^ANNMenuOf)(ANNNavigationOptions *options);
|
|
199
|
+
typedef void (^ANNSetMenu)(ANNNavigationOptions *options, ANNMenuOptions *menu);
|
|
200
|
+
|
|
201
|
+
static ANNUserChoice *ANNMenuChoice(NSArray<NSString *> *picks,
|
|
202
|
+
ANNMenuOf menuOf,
|
|
203
|
+
ANNSetMenu setMenu) {
|
|
204
|
+
return [ANNUserChoice choiceWithValue:picks
|
|
205
|
+
apply:^(ANNNavigationOptions *options, id value) {
|
|
206
|
+
ANNMenuOptions *menu = menuOf(options);
|
|
207
|
+
if (menu.items.count == 0) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
ANNMenuOptions *copy = [ANNBarButtons deepCopyOfMenu:menu];
|
|
211
|
+
for (NSString *itemId in (NSArray<NSString *> *)value) {
|
|
212
|
+
[copy itemPicked:itemId];
|
|
213
|
+
}
|
|
214
|
+
setMenu(options, copy);
|
|
215
|
+
}
|
|
216
|
+
merged:^id(id value, ANNNavigationOptions *merge, ANNNavigationOptions *own,
|
|
217
|
+
ANNNavigationOptions *before, ANNNavigationOptions *after) {
|
|
218
|
+
ANNMenuOptions *now = ANNMenuWithItems(menuOf(after));
|
|
219
|
+
ANNMenuOptions *given = ANNMenuWithItems(menuOf(merge));
|
|
220
|
+
ANNMenuOptions *was = ANNMenuWithItems(menuOf(own)) ?: ANNMenuWithItems(menuOf(before));
|
|
221
|
+
NSArray<NSString *> *made = value;
|
|
222
|
+
NSMutableArray<NSString *> *kept = [NSMutableArray new];
|
|
223
|
+
for (NSString *itemId in made) {
|
|
224
|
+
BOOL gone = !now || !ANNLevelOf(now.items, itemId);
|
|
225
|
+
NSSet<NSString *> *givenChecks = given ? ANNCheckedInLevel(given, itemId) : nil;
|
|
226
|
+
NSSet<NSString *> *wasChecks = ANNCheckedInLevel(was, itemId);
|
|
227
|
+
BOOL same = givenChecks == wasChecks || [givenChecks isEqualToSet:wasChecks];
|
|
228
|
+
BOOL changed = given && !same;
|
|
229
|
+
if (!gone && !changed) {
|
|
230
|
+
[kept addObject:itemId];
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
if (kept.count == 0) {
|
|
234
|
+
return nil;
|
|
235
|
+
}
|
|
236
|
+
return kept.count == made.count ? value : kept;
|
|
237
|
+
}];
|
|
238
|
+
}
|
|
239
|
+
|
|
57
240
|
static UIColor *ANNColorOf(Color *color) {
|
|
58
241
|
if (!color.hasValue || color.isNoColor) {
|
|
59
242
|
return nil;
|
|
@@ -119,6 +302,27 @@ static BOOL ANNHasComponent(ANNButtonOptions *button) {
|
|
|
119
302
|
[button.component.componentId withDefault:nil].length > 0;
|
|
120
303
|
}
|
|
121
304
|
|
|
305
|
+
// The image an icon loads, for telling builds apart (NSNull without one): a source of a file, data or Metro's server
|
|
306
|
+
// loads through the shared cache, which gives the same image until the file at its path changes or a failed load
|
|
307
|
+
// succeeds. An SF Symbol is the system's: its name in the options says it all.
|
|
308
|
+
static id ANNLoadedImageOf(Image *icon) {
|
|
309
|
+
ANNImageSource *source = icon.source;
|
|
310
|
+
if (!icon.hasValue || (source && source.kind == ANNImageSourceKindSymbol)) {
|
|
311
|
+
return NSNull.null;
|
|
312
|
+
}
|
|
313
|
+
return [icon withDefault:nil] ?: NSNull.null;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// The images the items of a menu load (an item with `sfSymbol` shows the symbol), at any depth.
|
|
317
|
+
static void ANNAddMenuImages(NSArray<ANNMenuItemOptions *> *items, NSMutableArray *loaded) {
|
|
318
|
+
for (ANNMenuItemOptions *item in items) {
|
|
319
|
+
if (!item.sfSymbol.hasValue) {
|
|
320
|
+
[loaded addObject:ANNLoadedImageOf(item.icon)];
|
|
321
|
+
}
|
|
322
|
+
ANNAddMenuImages(item.items, loaded);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
122
326
|
// The image button's background: its own `iconBackground.color`, else (only for an image icon) the side's.
|
|
123
327
|
static UIColor *ANNIconBackgroundOf(ANNButtonOptions *button, Color *sideBackground) {
|
|
124
328
|
UIColor *own = ANNColorOf(button.iconBackground.color);
|
|
@@ -212,6 +416,60 @@ static UIBarButtonSystemItem ANNSystemItemOf(NSString *name) {
|
|
|
212
416
|
@implementation ANNButtonPress
|
|
213
417
|
@end
|
|
214
418
|
|
|
419
|
+
// The same objects, one by one: what a build read by identity (a loaded image, a React button's slot) and what it put
|
|
420
|
+
// on the navigation item. A string (the item's customization id) by its value.
|
|
421
|
+
static BOOL ANNSameObjects(NSArray *a, NSArray *b) {
|
|
422
|
+
if (a.count != b.count) {
|
|
423
|
+
return NO;
|
|
424
|
+
}
|
|
425
|
+
for (NSUInteger index = 0; index < a.count; index++) {
|
|
426
|
+
id mine = a[index];
|
|
427
|
+
id theirs = b[index];
|
|
428
|
+
if (mine != theirs && !([mine isKindOfClass:NSString.class] && [mine isEqual:theirs])) {
|
|
429
|
+
return NO;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return YES;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// Everything the build of one side reads: the side's buttons, its colors and the customization id of the middle by
|
|
436
|
+
// value; the images it loads and the slots of its React buttons by identity (a file written again at its path loads as
|
|
437
|
+
// another image, a reload gives other roots); the traits it builds under (a text button's font follows the text size,
|
|
438
|
+
// a drawn image the scale and the style).
|
|
439
|
+
@interface ANNSideInputs : NSObject
|
|
440
|
+
@property(nonatomic, strong, nullable) NSArray<ANNButtonOptions *> *buttons;
|
|
441
|
+
@property(nonatomic, strong, nullable) Color *color;
|
|
442
|
+
@property(nonatomic, strong, nullable) Color *disabledColor;
|
|
443
|
+
@property(nonatomic, strong, nullable) Color *background;
|
|
444
|
+
@property(nonatomic, strong, nullable) Text *customizationId;
|
|
445
|
+
@property(nonatomic, copy) NSArray *loaded;
|
|
446
|
+
@property(nonatomic, copy) NSArray *traits;
|
|
447
|
+
@end
|
|
448
|
+
|
|
449
|
+
@implementation ANNSideInputs
|
|
450
|
+
|
|
451
|
+
- (BOOL)isSameAs:(ANNSideInputs *)other {
|
|
452
|
+
return ANNOptionValuesSame(_buttons, other.buttons) &&
|
|
453
|
+
ANNOptionValuesSame(_color, other.color) &&
|
|
454
|
+
ANNOptionValuesSame(_disabledColor, other.disabledColor) &&
|
|
455
|
+
ANNOptionValuesSame(_background, other.background) &&
|
|
456
|
+
ANNOptionValuesSame(_customizationId, other.customizationId) &&
|
|
457
|
+
ANNSameObjects(_loaded, other.loaded) && [_traits isEqualToArray:other.traits];
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
@end
|
|
461
|
+
|
|
462
|
+
// The last build of one side: what it read and what the navigation item held right after it.
|
|
463
|
+
@interface ANNSideBuild : NSObject
|
|
464
|
+
@property(nonatomic, strong) ANNSideInputs *inputs;
|
|
465
|
+
// The side went in as groups (`leadingItemGroups`, …), not as a list of items.
|
|
466
|
+
@property(nonatomic) BOOL grouped;
|
|
467
|
+
@property(nonatomic, copy) NSArray *placed;
|
|
468
|
+
@end
|
|
469
|
+
|
|
470
|
+
@implementation ANNSideBuild
|
|
471
|
+
@end
|
|
472
|
+
|
|
215
473
|
@implementation ANNBarButtons {
|
|
216
474
|
__weak UIViewController *_screen;
|
|
217
475
|
ANNReactComponentRegistry *_registry;
|
|
@@ -220,6 +478,8 @@ static UIBarButtonSystemItem ANNSystemItemOf(NSString *name) {
|
|
|
220
478
|
NSMutableDictionary<NSString *, NSNumber *> *_selected;
|
|
221
479
|
// What a press of each sender (an item, a button of an item) means.
|
|
222
480
|
NSMapTable<id, ANNButtonPress *> *_presses;
|
|
481
|
+
// The last build of each side, by the side.
|
|
482
|
+
NSMutableDictionary<NSNumber *, ANNSideBuild *> *_builds;
|
|
223
483
|
}
|
|
224
484
|
|
|
225
485
|
- (instancetype)initWithScreen:(UIViewController *)screen
|
|
@@ -230,12 +490,16 @@ static UIBarButtonSystemItem ANNSystemItemOf(NSString *name) {
|
|
|
230
490
|
_slots = [NSMutableDictionary new];
|
|
231
491
|
_selected = [NSMutableDictionary new];
|
|
232
492
|
_presses = [NSMapTable weakToStrongObjectsMapTable];
|
|
493
|
+
_builds = [NSMutableDictionary new];
|
|
233
494
|
}
|
|
234
495
|
return self;
|
|
235
496
|
}
|
|
236
497
|
|
|
237
498
|
#pragma mark - The sides
|
|
238
499
|
|
|
500
|
+
// From iOS 26 UIKit animates any change of the bar's items, also to equal ones and with `animated:NO`: new items on
|
|
501
|
+
// each appearance would morph, close an open menu and drop a pressed state. So a side is built again only when what
|
|
502
|
+
// its build reads changed, or when the item no longer holds what the last build put there.
|
|
239
503
|
- (void)applySide:(ANNBarButtonsSide)side
|
|
240
504
|
options:(ANNNavigationOptions *)options
|
|
241
505
|
animated:(BOOL)animated {
|
|
@@ -244,12 +508,92 @@ static UIBarButtonSystemItem ANNSystemItemOf(NSString *name) {
|
|
|
244
508
|
return;
|
|
245
509
|
}
|
|
246
510
|
UINavigationItem *navigationItem = screen.navigationItem;
|
|
511
|
+
ANNSideInputs *inputs = [self inputsOfSide:side options:options];
|
|
512
|
+
ANNSideBuild *last = _builds[@(side)];
|
|
513
|
+
if (last && [last.inputs isSameAs:inputs]) {
|
|
514
|
+
NSArray *placed = [self placedOf:side grouped:last.grouped item:navigationItem];
|
|
515
|
+
if (ANNSameObjects(last.placed, placed)) {
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
ANNSideBuild *build = [ANNSideBuild new];
|
|
520
|
+
build.inputs = inputs;
|
|
521
|
+
build.grouped = [self placeSide:side options:options item:navigationItem animated:animated];
|
|
522
|
+
build.placed = [self placedOf:side grouped:build.grouped item:navigationItem];
|
|
523
|
+
_builds[@(side)] = build;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
- (ANNSideInputs *)inputsOfSide:(ANNBarButtonsSide)side options:(ANNNavigationOptions *)options {
|
|
527
|
+
ANNTopBarOptions *topBar = options.topBar;
|
|
528
|
+
ANNSideInputs *inputs = [ANNSideInputs new];
|
|
529
|
+
inputs.buttons = ANNButtonsOfSide(options, side);
|
|
530
|
+
inputs.color = ANNSideColor(topBar, side);
|
|
531
|
+
inputs.disabledColor = ANNSideDisabledColor(topBar, side);
|
|
532
|
+
inputs.background = ANNSideBackgroundColor(topBar, side);
|
|
533
|
+
inputs.customizationId = side == ANNBarButtonsSideCenter ? topBar.customizationId : nil;
|
|
534
|
+
NSMutableArray *loaded = [NSMutableArray new];
|
|
535
|
+
for (ANNButtonOptions *button in inputs.buttons ?: @[]) {
|
|
536
|
+
if (ANNHasComponent(button)) {
|
|
537
|
+
[loaded addObject:[self slotFor:button] ?: NSNull.null];
|
|
538
|
+
}
|
|
539
|
+
[loaded addObject:ANNLoadedImageOf(button.icon)];
|
|
540
|
+
ANNAddMenuImages(button.menu.items, loaded);
|
|
541
|
+
}
|
|
542
|
+
inputs.loaded = loaded;
|
|
543
|
+
UITraitCollection *traits = UITraitCollection.currentTraitCollection;
|
|
544
|
+
inputs.traits = @[
|
|
545
|
+
@(traits.userInterfaceStyle), @(traits.displayScale),
|
|
546
|
+
traits.preferredContentSizeCategory ?: @"", @(traits.legibilityWeight)
|
|
547
|
+
];
|
|
548
|
+
return inputs;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// What the navigation item holds of `side` now, as the side's build put it there.
|
|
552
|
+
- (NSArray *)placedOf:(ANNBarButtonsSide)side
|
|
553
|
+
grouped:(BOOL)grouped
|
|
554
|
+
item:(UINavigationItem *)navigationItem {
|
|
555
|
+
NSMutableArray *placed = [NSMutableArray new];
|
|
556
|
+
BOOL left = side == ANNBarButtonsSideLeft;
|
|
557
|
+
switch (side) {
|
|
558
|
+
case ANNBarButtonsSideLeft:
|
|
559
|
+
case ANNBarButtonsSideRight: {
|
|
560
|
+
NSArray *shown =
|
|
561
|
+
left ? navigationItem.leftBarButtonItems : navigationItem.rightBarButtonItems;
|
|
562
|
+
if (@available(iOS 16.0, *)) {
|
|
563
|
+
if (grouped) {
|
|
564
|
+
shown = left ? navigationItem.leadingItemGroups
|
|
565
|
+
: navigationItem.trailingItemGroups;
|
|
566
|
+
}
|
|
567
|
+
if (!left) {
|
|
568
|
+
[placed addObject:navigationItem.pinnedTrailingGroup ?: NSNull.null];
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
[placed addObjectsFromArray:shown ?: @[]];
|
|
572
|
+
break;
|
|
573
|
+
}
|
|
574
|
+
case ANNBarButtonsSideCenter:
|
|
575
|
+
if (@available(iOS 16.0, *)) {
|
|
576
|
+
[placed addObjectsFromArray:navigationItem.centerItemGroups ?: @[]];
|
|
577
|
+
[placed addObject:navigationItem.customizationIdentifier ?: NSNull.null];
|
|
578
|
+
}
|
|
579
|
+
break;
|
|
580
|
+
case ANNBarButtonsSideToolbar:
|
|
581
|
+
break;
|
|
582
|
+
}
|
|
583
|
+
return placed;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// Builds `side` whole and puts it on the item; YES when it went in as groups.
|
|
587
|
+
- (BOOL)placeSide:(ANNBarButtonsSide)side
|
|
588
|
+
options:(ANNNavigationOptions *)options
|
|
589
|
+
item:(UINavigationItem *)navigationItem
|
|
590
|
+
animated:(BOOL)animated {
|
|
247
591
|
NSArray<ANNBuiltButton *> *built = [self buildSide:side options:options];
|
|
248
592
|
if (side == ANNBarButtonsSideCenter) {
|
|
249
593
|
if (@available(iOS 16.0, *)) {
|
|
250
594
|
[self setCenter:built options:options item:navigationItem];
|
|
251
595
|
}
|
|
252
|
-
return;
|
|
596
|
+
return YES;
|
|
253
597
|
}
|
|
254
598
|
NSMutableArray<ANNBuiltButton *> *placed = [built mutableCopy];
|
|
255
599
|
if (side == ANNBarButtonsSideRight) {
|
|
@@ -258,26 +602,28 @@ static UIBarButtonSystemItem ANNSystemItemOf(NSString *name) {
|
|
|
258
602
|
}
|
|
259
603
|
}
|
|
260
604
|
if (@available(iOS 26.0, *)) {
|
|
261
|
-
if ([self hasGroupOfSeveral:placed]) {
|
|
605
|
+
if (ANNTabsDesign.isGlass && [self hasGroupOfSeveral:placed]) {
|
|
262
606
|
NSArray<UIBarButtonItemGroup *> *groups = [self groupsOf:placed];
|
|
263
607
|
if (side == ANNBarButtonsSideLeft) {
|
|
264
608
|
navigationItem.leadingItemGroups = groups;
|
|
265
609
|
} else {
|
|
266
610
|
navigationItem.trailingItemGroups = groups.reverseObjectEnumerator.allObjects;
|
|
267
611
|
}
|
|
268
|
-
return;
|
|
612
|
+
return YES;
|
|
269
613
|
}
|
|
270
614
|
}
|
|
271
615
|
NSMutableArray<UIBarButtonItem *> *items = [NSMutableArray new];
|
|
272
616
|
for (ANNBuiltButton *button in placed) {
|
|
273
617
|
if (@available(iOS 26.0, *)) {
|
|
274
618
|
// Each button its own capsule: a zero-width space between neighbours, and the right ones never share the
|
|
275
|
-
// capsule of "•••".
|
|
276
|
-
if (
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
619
|
+
// capsule of "•••". The compatibility mode has no capsules.
|
|
620
|
+
if (ANNTabsDesign.isGlass) {
|
|
621
|
+
if (items.count > 0) {
|
|
622
|
+
[items addObject:[UIBarButtonItem fixedSpaceItemOfWidth:0]];
|
|
623
|
+
}
|
|
624
|
+
if (side == ANNBarButtonsSideRight) {
|
|
625
|
+
button.item.sharesBackground = NO;
|
|
626
|
+
}
|
|
281
627
|
}
|
|
282
628
|
}
|
|
283
629
|
[items addObject:button.item];
|
|
@@ -287,6 +633,7 @@ static UIBarButtonSystemItem ANNSystemItemOf(NSString *name) {
|
|
|
287
633
|
} else {
|
|
288
634
|
[navigationItem setRightBarButtonItems:items animated:animated];
|
|
289
635
|
}
|
|
636
|
+
return NO;
|
|
290
637
|
}
|
|
291
638
|
|
|
292
639
|
- (NSArray<ANNBuiltButton *> *)buildSide:(ANNBarButtonsSide)side
|
|
@@ -377,7 +724,7 @@ static UIBarButtonSystemItem ANNSystemItemOf(NSString *name) {
|
|
|
377
724
|
NSMutableArray<UIBarButtonItem *> *items = [NSMutableArray new];
|
|
378
725
|
for (ANNBuiltButton *button in run) {
|
|
379
726
|
if (@available(iOS 26.0, *)) {
|
|
380
|
-
if (run.count == 1) {
|
|
727
|
+
if (run.count == 1 && ANNTabsDesign.isGlass) {
|
|
381
728
|
button.item.sharesBackground = NO;
|
|
382
729
|
}
|
|
383
730
|
}
|
|
@@ -438,11 +785,12 @@ static UIBarButtonSystemItem ANNSystemItemOf(NSString *name) {
|
|
|
438
785
|
}
|
|
439
786
|
UIMenu *built = [current menuWithPickHandler:^(NSString *itemId) {
|
|
440
787
|
[weakSelf menuItemPicked:itemId
|
|
441
|
-
|
|
442
|
-
|
|
788
|
+
choiceKey:@"topBar.overflowMenu"
|
|
789
|
+
menuOf:^ANNMenuOptions *(ANNNavigationOptions *options) {
|
|
790
|
+
return options.topBar.overflowMenu;
|
|
443
791
|
}
|
|
444
|
-
setMenu:^(ANNNavigationOptions *
|
|
445
|
-
|
|
792
|
+
setMenu:^(ANNNavigationOptions *options, ANNMenuOptions *copy) {
|
|
793
|
+
options.topBar.overflowMenu = copy;
|
|
446
794
|
}];
|
|
447
795
|
}];
|
|
448
796
|
UIMenu *section = [UIMenu menuWithTitle:built.title
|
|
@@ -484,7 +832,7 @@ static UIBarButtonSystemItem ANNSystemItemOf(NSString *name) {
|
|
|
484
832
|
BOOL icon = kind == ANNBarButtonKindSymbol || kind == ANNBarButtonKindImage ||
|
|
485
833
|
kind == ANNBarButtonKindImageButton || kind == ANNBarButtonKindShowText;
|
|
486
834
|
NSString *group = icon ? [button.group withDefault:nil] : nil;
|
|
487
|
-
if (
|
|
835
|
+
if (ANNTabsDesign.isGlass) {
|
|
488
836
|
// Only icons of one group share a capsule (the toolbar has no groups): any other neighbours get a
|
|
489
837
|
// zero-width space, unless a space of the options is there already.
|
|
490
838
|
BOOL sameGroup = group.length > 0 && [group isEqualToString:previousIconGroup];
|
|
@@ -652,10 +1000,12 @@ static UIBarButtonSystemItem ANNSystemItemOf(NSString *name) {
|
|
|
652
1000
|
}
|
|
653
1001
|
BOOL prominent = [[button.style withDefault:nil] isEqualToString:@"prominent"];
|
|
654
1002
|
if (prominent) {
|
|
1003
|
+
// The capsule of the glass; the design before it (and its compatibility mode) has the bold `done` style.
|
|
1004
|
+
item.style = UIBarButtonItemStyleDone;
|
|
655
1005
|
if (@available(iOS 26.0, *)) {
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
1006
|
+
if (ANNTabsDesign.isGlass) {
|
|
1007
|
+
item.style = UIBarButtonItemStyleProminent;
|
|
1008
|
+
}
|
|
659
1009
|
}
|
|
660
1010
|
}
|
|
661
1011
|
// The color: the tint, and for a plain button also the text's; `prominent` takes it only into the tint, and a font
|
|
@@ -838,9 +1188,11 @@ static UIBarButtonSystemItem ANNSystemItemOf(NSString *name) {
|
|
|
838
1188
|
kind:(ANNBarButtonKind)kind
|
|
839
1189
|
to:(UIBarButtonItem *)item {
|
|
840
1190
|
if (@available(iOS 26.0, *)) {
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
1191
|
+
if (ANNTabsDesign.isGlass) {
|
|
1192
|
+
BOOL ownBackground =
|
|
1193
|
+
kind == ANNBarButtonKindComponent || kind == ANNBarButtonKindImageButton;
|
|
1194
|
+
item.hidesSharedBackground = [button.hideSharedBackground withDefault:ownBackground];
|
|
1195
|
+
}
|
|
844
1196
|
}
|
|
845
1197
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 270000
|
|
846
1198
|
if (@available(iOS 27.0, *)) {
|
|
@@ -880,16 +1232,14 @@ static UIBarButtonSystemItem ANNSystemItemOf(NSString *name) {
|
|
|
880
1232
|
__weak ANNBarButtons *weakSelf = self;
|
|
881
1233
|
item.menu = [menu menuWithPickHandler:^(NSString *itemId) {
|
|
882
1234
|
[weakSelf menuItemPicked:itemId
|
|
1235
|
+
choiceKey:ANNButtonMenuChoiceKey(side, buttonId)
|
|
883
1236
|
menuOf:^ANNMenuOptions *(ANNNavigationOptions *options) {
|
|
884
|
-
return
|
|
1237
|
+
return ANNButtonWithId(ANNButtonsOfSide(options, side), buttonId).menu;
|
|
885
1238
|
}
|
|
886
|
-
setMenu:^(ANNNavigationOptions *
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
change:^(ANNButtonOptions *changed) {
|
|
891
|
-
changed.menu = copy;
|
|
892
|
-
}];
|
|
1239
|
+
setMenu:^(ANNNavigationOptions *options, ANNMenuOptions *copy) {
|
|
1240
|
+
ANNChangeButton(options, side, buttonId, ^(ANNButtonOptions *changed) {
|
|
1241
|
+
changed.menu = copy;
|
|
1242
|
+
});
|
|
893
1243
|
}];
|
|
894
1244
|
}];
|
|
895
1245
|
if (![button.menuOnLongPress withDefault:NO]) {
|
|
@@ -948,22 +1298,15 @@ static UIBarButtonSystemItem ANNSystemItemOf(NSString *name) {
|
|
|
948
1298
|
[screen.eventEmitter sendOnNavigationButtonPressed:componentId buttonId:press.buttonId];
|
|
949
1299
|
return;
|
|
950
1300
|
}
|
|
951
|
-
// A toggle flips, the
|
|
1301
|
+
// A toggle flips, the user layer keeps the new state, then the event tells it.
|
|
952
1302
|
ANNUIBarButtonItem *item = press.item;
|
|
953
1303
|
BOOL selected = !item.selected;
|
|
954
1304
|
item.selected = selected;
|
|
955
1305
|
_selected[press.buttonId] = @(selected);
|
|
956
|
-
__weak ANNBarButtons *weakSelf = self;
|
|
957
1306
|
NSString *buttonId = press.buttonId;
|
|
958
1307
|
ANNBarButtonsSide side = press.side;
|
|
959
|
-
[screen
|
|
960
|
-
|
|
961
|
-
side:side
|
|
962
|
-
inOwn:own
|
|
963
|
-
change:^(ANNButtonOptions *changed) {
|
|
964
|
-
changed.selected = [Bool withValue:selected];
|
|
965
|
-
}];
|
|
966
|
-
}];
|
|
1308
|
+
[screen setUserChoice:ANNToggleChoice(side, buttonId, selected)
|
|
1309
|
+
forKey:ANNToggleChoiceKey(side, buttonId)];
|
|
967
1310
|
[screen.eventEmitter sendOnNavigationButtonPressed:componentId
|
|
968
1311
|
buttonId:buttonId
|
|
969
1312
|
selected:@(selected)];
|
|
@@ -971,46 +1314,15 @@ static UIBarButtonSystemItem ANNSystemItemOf(NSString *name) {
|
|
|
971
1314
|
|
|
972
1315
|
+ (nullable ANNButtonOptions *)buttonWithId:(NSString *)buttonId
|
|
973
1316
|
in:(NSArray<ANNButtonOptions *> *)buttons {
|
|
974
|
-
|
|
975
|
-
if ([[button.identifier withDefault:nil] isEqualToString:buttonId]) {
|
|
976
|
-
return button;
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
return nil;
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
// The button `buttonId` of `side` in the own options, changed on a copy: the own list when it has the button, else the
|
|
983
|
-
// list the screen shows (from its stack or the defaults), copied into the own options first. Lists are new arrays.
|
|
984
|
-
- (void)changeButton:(NSString *)buttonId
|
|
985
|
-
side:(ANNBarButtonsSide)side
|
|
986
|
-
inOwn:(ANNNavigationOptions *)own
|
|
987
|
-
change:(void (^)(ANNButtonOptions *changed))change {
|
|
988
|
-
NSArray<ANNButtonOptions *> *list = ANNButtonsOfSide(own, side);
|
|
989
|
-
if (![ANNBarButtons buttonWithId:buttonId in:list]) {
|
|
990
|
-
list = ANNButtonsOfSide([_screen resolveOptionsWithDefault], side);
|
|
991
|
-
}
|
|
992
|
-
if (![ANNBarButtons buttonWithId:buttonId in:list]) {
|
|
993
|
-
return;
|
|
994
|
-
}
|
|
995
|
-
NSMutableArray<ANNButtonOptions *> *changedList = [NSMutableArray arrayWithCapacity:list.count];
|
|
996
|
-
for (ANNButtonOptions *button in list) {
|
|
997
|
-
ANNButtonOptions *copy = [button copy];
|
|
998
|
-
if (button.menu.items.count > 0) {
|
|
999
|
-
copy.menu = [ANNBarButtons deepCopyOfMenu:button.menu];
|
|
1000
|
-
}
|
|
1001
|
-
if ([[button.identifier withDefault:nil] isEqualToString:buttonId]) {
|
|
1002
|
-
change(copy);
|
|
1003
|
-
}
|
|
1004
|
-
[changedList addObject:copy];
|
|
1005
|
-
}
|
|
1006
|
-
ANNSetButtonsOfSide(own, side, changedList);
|
|
1317
|
+
return ANNButtonWithId(buttons, buttonId);
|
|
1007
1318
|
}
|
|
1008
1319
|
|
|
1009
1320
|
#pragma mark - Menus
|
|
1010
1321
|
|
|
1011
1322
|
- (void)menuItemPicked:(NSString *)itemId
|
|
1323
|
+
choiceKey:(NSString *)choiceKey
|
|
1012
1324
|
menuOf:(ANNMenuOptions *_Nullable (^)(ANNNavigationOptions *options))menuOf
|
|
1013
|
-
setMenu:(void (^)(ANNNavigationOptions *
|
|
1325
|
+
setMenu:(void (^)(ANNNavigationOptions *options, ANNMenuOptions *menu))setMenu {
|
|
1014
1326
|
UIViewController *screen = _screen;
|
|
1015
1327
|
NSString *componentId = screen.layoutInfo.componentId;
|
|
1016
1328
|
if (!screen || componentId.length == 0) {
|
|
@@ -1021,13 +1333,18 @@ static UIBarButtonSystemItem ANNSystemItemOf(NSString *name) {
|
|
|
1021
1333
|
if (!menu || ![ANNBarButtons menu:menu hasSingleSelectionOf:itemId]) {
|
|
1022
1334
|
return;
|
|
1023
1335
|
}
|
|
1024
|
-
// The
|
|
1025
|
-
//
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1336
|
+
// The new pick goes last; the earlier picks of its own list go, so a pick the app takes away later doesn't bring
|
|
1337
|
+
// back one the user replaced.
|
|
1338
|
+
NSArray<NSString *> *made = [screen userChoiceForKey:choiceKey].value ?: @[];
|
|
1339
|
+
NSArray<NSString *> *neighbors = ANNNeighborsOf(menu.items, itemId);
|
|
1340
|
+
NSMutableArray<NSString *> *picks = [NSMutableArray new];
|
|
1341
|
+
for (NSString *pick in made) {
|
|
1342
|
+
if (![neighbors containsObject:pick]) {
|
|
1343
|
+
[picks addObject:pick];
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
[picks addObject:itemId];
|
|
1347
|
+
[screen setUserChoice:ANNMenuChoice(picks, menuOf, setMenu) forKey:choiceKey];
|
|
1031
1348
|
}
|
|
1032
1349
|
|
|
1033
1350
|
+ (BOOL)menu:(ANNMenuOptions *)menu hasSingleSelectionOf:(NSString *)itemId {
|
|
@@ -13,6 +13,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
13
13
|
|
|
14
14
|
/// `tint` colors the icon (nil: its own colors); `background` fills the rectangle of `size` (zero: the icon's size)
|
|
15
15
|
/// rounded by `cornerRadius`; `insets` pad the icon. Colors may be dynamic: each variant resolves them.
|
|
16
|
+
/// An icon that can't be drawn so (no room, an exception while drawing) comes back as it is.
|
|
16
17
|
+ (UIImage *)imageWithIcon:(UIImage *)icon
|
|
17
18
|
tint:(nullable UIColor *)tint
|
|
18
19
|
background:(nullable UIColor *)background
|