@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
package/android/src/main/java/dev/apexnative/navigation/options/HardwareBackButtonOptions.kt
CHANGED
|
@@ -15,20 +15,27 @@ class HardwareBackButtonOptions {
|
|
|
15
15
|
@JvmField var popStackOnPress: Bool = NullBool()
|
|
16
16
|
/** Internal. */
|
|
17
17
|
@JvmField var dismissModalOnPress: Bool = NullBool()
|
|
18
|
+
/**
|
|
19
|
+
* `systemAnimation`: `false` keeps back in the app on the first screen too, so the system doesn't play its
|
|
20
|
+
* animation of going home; the press then does the activity's own back.
|
|
21
|
+
*/
|
|
22
|
+
@JvmField var systemAnimation: Bool = NullBool()
|
|
18
23
|
|
|
19
24
|
fun hasValue(): Boolean = bottomTabsOnPress.hasValue() || popStackOnPress.hasValue() ||
|
|
20
|
-
dismissModalOnPress.hasValue()
|
|
25
|
+
dismissModalOnPress.hasValue() || systemAnimation.hasValue()
|
|
21
26
|
|
|
22
27
|
fun mergeWith(other: HardwareBackButtonOptions) {
|
|
23
28
|
if (other.bottomTabsOnPress.hasValue()) bottomTabsOnPress = other.bottomTabsOnPress
|
|
24
29
|
if (other.popStackOnPress.hasValue()) popStackOnPress = other.popStackOnPress
|
|
25
30
|
if (other.dismissModalOnPress.hasValue()) dismissModalOnPress = other.dismissModalOnPress
|
|
31
|
+
if (other.systemAnimation.hasValue()) systemAnimation = other.systemAnimation
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
fun mergeWithDefault(defaults: HardwareBackButtonOptions) {
|
|
29
35
|
if (!bottomTabsOnPress.hasValue()) bottomTabsOnPress = defaults.bottomTabsOnPress
|
|
30
36
|
if (!popStackOnPress.hasValue()) popStackOnPress = defaults.popStackOnPress
|
|
31
37
|
if (!dismissModalOnPress.hasValue()) dismissModalOnPress = defaults.dismissModalOnPress
|
|
38
|
+
if (!systemAnimation.hasValue()) systemAnimation = defaults.systemAnimation
|
|
32
39
|
}
|
|
33
40
|
|
|
34
41
|
fun copy() = HardwareBackButtonOptions().also { it.mergeWith(this) }
|
|
@@ -43,6 +50,7 @@ class HardwareBackButtonOptions {
|
|
|
43
50
|
options.bottomTabsOnPress = TextParser.parse(map, "bottomTabsOnPress", BOTTOM_TABS_ON_PRESS)
|
|
44
51
|
options.popStackOnPress = BoolParser.parse(map, "popStackOnPress")
|
|
45
52
|
options.dismissModalOnPress = BoolParser.parse(map, "dismissModalOnPress")
|
|
53
|
+
options.systemAnimation = BoolParser.parse(map, "systemAnimation")
|
|
46
54
|
return options
|
|
47
55
|
}
|
|
48
56
|
}
|
|
@@ -22,7 +22,7 @@ class LargeTitleOptions {
|
|
|
22
22
|
@JvmField var collapseOnScroll: Bool = NullBool()
|
|
23
23
|
@JvmField var fontSize: Fraction = NullFraction()
|
|
24
24
|
@JvmField var color: ThemeColour = NullThemeColour()
|
|
25
|
-
@JvmField var font = FontOptions()
|
|
25
|
+
@ReadFromParent @JvmField var font = FontOptions()
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* When the large title shows: [ALWAYS], [NEVER] or [AUTOMATIC], as on the screen below. `displayMode` over
|
|
@@ -9,7 +9,7 @@ import com.facebook.react.bridge.ReadableMap
|
|
|
9
9
|
* first).
|
|
10
10
|
*/
|
|
11
11
|
open class LayoutAnimation(
|
|
12
|
-
@JvmField var sharedElements: SharedElements = SharedElements(),
|
|
12
|
+
@OptionKey("sharedElementTransitions") @JvmField var sharedElements: SharedElements = SharedElements(),
|
|
13
13
|
@JvmField var elementTransitions: ElementTransitions = ElementTransitions(),
|
|
14
14
|
) {
|
|
15
15
|
open fun hasValue(): Boolean = sharedElements.hasValue() || elementTransitions.hasValue()
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
package dev.apexnative.navigation.options
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The JSON key of an option field whose name is not that key (`topBar.backButton` is `TopBarButtons.back`), for the
|
|
5
|
+
* paths of [OptionPaths]; also the flag that tells a value is given, which goes with it. A field without it answers to
|
|
6
|
+
* its own name.
|
|
7
|
+
*/
|
|
8
|
+
@Target(AnnotationTarget.FIELD)
|
|
9
|
+
@Retention(AnnotationRetention.RUNTIME)
|
|
10
|
+
annotation class OptionKey(val name: String)
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A group the reader takes from the object of the group that holds it, not from a key of its own (the font of a text,
|
|
14
|
+
* the top bar's buttons): for the paths of [OptionPaths] its fields answer to the keys of that object.
|
|
15
|
+
*/
|
|
16
|
+
@Target(AnnotationTarget.FIELD)
|
|
17
|
+
@Retention(AnnotationRetention.RUNTIME)
|
|
18
|
+
annotation class ReadFromParent
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
package dev.apexnative.navigation.options
|
|
2
|
+
|
|
3
|
+
import dev.apexnative.navigation.options.params.Param
|
|
4
|
+
import dev.apexnative.navigation.options.params.ThemeColour
|
|
5
|
+
import java.lang.reflect.Field
|
|
6
|
+
import java.lang.reflect.Modifier
|
|
7
|
+
import java.util.concurrent.ConcurrentHashMap
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The options at a JSON key path, the keys of the options joined with dots (`topBar.subtitle`, `bottomTab.badge`), as
|
|
11
|
+
* the readers parse them: `clearOptions` takes them out of a node's own options. Generic over the whole tree, by
|
|
12
|
+
* reflection on the fields of the groups: a field answers to the key of its name, or of its [OptionKey]; a group the
|
|
13
|
+
* reader takes from the object of its parent ([ReadFromParent]: the font of a text, the top bar's buttons) answers with
|
|
14
|
+
* its fields to the keys of that object. A group is a class with a `mergeWith` of its own class; anything else (a
|
|
15
|
+
* value, a color, a list, a button menu) ends a path.
|
|
16
|
+
*/
|
|
17
|
+
internal object OptionPaths {
|
|
18
|
+
/**
|
|
19
|
+
* What a path names: the fields of [group] that answer to its last key, [members] (one, or a value and the flag
|
|
20
|
+
* that tells it is given, as `modal.sheet.largestUndimmedDetent`).
|
|
21
|
+
*/
|
|
22
|
+
class Place(val group: Any, val members: List<Field>) {
|
|
23
|
+
/** The value at the path, of the first field. */
|
|
24
|
+
val value: Any? get() = members.first().get(group)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// The fields of each class walked, its superclasses' first.
|
|
28
|
+
private val fieldsOfType = ConcurrentHashMap<Class<*>, List<Field>>()
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Takes the value at [path] out of [options], which it changes in place: the field gets the value a freshly made
|
|
32
|
+
* group has for it (unset; a group, an empty one). Whether the path names a field; an empty or unknown path, or
|
|
33
|
+
* one that goes on inside a value (a side of a color), changes nothing.
|
|
34
|
+
*/
|
|
35
|
+
fun clear(options: Options, path: String): Boolean {
|
|
36
|
+
val place = find(options, path) ?: return false
|
|
37
|
+
val fresh = newGroup(place.group.javaClass) ?: return false
|
|
38
|
+
place.members.forEach { it.set(place.group, it.get(fresh)) }
|
|
39
|
+
return true
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** The fields [path] names in [options]; none for an empty or unknown path or one inside a value. */
|
|
43
|
+
fun find(options: Options, path: String): Place? {
|
|
44
|
+
val keys = path.split('.')
|
|
45
|
+
if (keys.any(String::isEmpty)) return null
|
|
46
|
+
var group: Any = options
|
|
47
|
+
for (key in keys.dropLast(1)) {
|
|
48
|
+
group = fieldOf(group, key)?.value?.takeIf(::isGroup) ?: return null
|
|
49
|
+
}
|
|
50
|
+
return fieldOf(group, keys.last())?.takeIf { newGroup(it.group.javaClass) != null }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// The fields of [group] that answer to [key]: its own, else those of a group read from the same object.
|
|
54
|
+
private fun fieldOf(group: Any, key: String): Place? {
|
|
55
|
+
val fields = fieldsOf(group.javaClass)
|
|
56
|
+
fields.filter { !it.isAnnotationPresent(ReadFromParent::class.java) && keyOf(it) == key }
|
|
57
|
+
.takeIf { it.isNotEmpty() }
|
|
58
|
+
?.let { return Place(group, it) }
|
|
59
|
+
for (field in fields) {
|
|
60
|
+
if (!field.isAnnotationPresent(ReadFromParent::class.java)) continue
|
|
61
|
+
val inner = field.get(group)?.takeIf(::isGroup) ?: continue
|
|
62
|
+
fieldOf(inner, key)?.let { return it }
|
|
63
|
+
}
|
|
64
|
+
return null
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private fun keyOf(field: Field): String = field.getAnnotation(OptionKey::class.java)?.name ?: field.name
|
|
68
|
+
|
|
69
|
+
private fun fieldsOf(type: Class<*>): List<Field> = fieldsOfType.getOrPut(type) {
|
|
70
|
+
generateSequence(type) { it.superclass }
|
|
71
|
+
.takeWhile { it != Any::class.java }
|
|
72
|
+
.toList()
|
|
73
|
+
.asReversed()
|
|
74
|
+
.flatMap { it.declaredFields.asList() }
|
|
75
|
+
.filter { !Modifier.isStatic(it.modifiers) && !it.isSynthetic }
|
|
76
|
+
.onEach { it.isAccessible = true }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private fun isGroup(value: Any): Boolean {
|
|
80
|
+
if (value is Param<*> || value is ThemeColour) return false
|
|
81
|
+
val type = value.javaClass
|
|
82
|
+
return type.declaredMethods.any { it.name == "mergeWith" && it.parameterTypes.contentEquals(arrayOf(type)) }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// A group as its class makes it, every field unset; none for a class without a constructor of no arguments.
|
|
86
|
+
private fun newGroup(type: Class<*>): Any? = try {
|
|
87
|
+
type.getDeclaredConstructor().newInstance()
|
|
88
|
+
} catch (_: ReflectiveOperationException) {
|
|
89
|
+
null
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -3,9 +3,10 @@ package dev.apexnative.navigation.options
|
|
|
3
3
|
/**
|
|
4
4
|
* The one point where the options of the app change: a process-wide generation that grows at each change. A node's
|
|
5
5
|
* resolved options are kept while the generation stays and the nodes they were built along are the same
|
|
6
|
-
* (`ViewController.resolveCurrentOptions`).
|
|
7
|
-
* (`ViewController.options`, and `changeOptions` through it)
|
|
8
|
-
* (
|
|
6
|
+
* (`ViewController.resolveCurrentOptions`). Three places call [optionsChanged]: the write of a node's own options
|
|
7
|
+
* (`ViewController.options`, and `changeOptions` and `mergeOwnOptions` through it), the write of a node's user layer
|
|
8
|
+
* (`ViewController.changeChoices`, and a merge that takes a choice away) and the store of new default options
|
|
9
|
+
* ([DefaultOptions.set]). Nothing else changes a node's own options, its user layer or the defaults. Main thread only.
|
|
9
10
|
*/
|
|
10
11
|
object OptionsCache {
|
|
11
12
|
/** The generation of the options; it only grows. */
|
|
@@ -13,7 +14,10 @@ object OptionsCache {
|
|
|
13
14
|
var generation: Long = 0
|
|
14
15
|
private set
|
|
15
16
|
|
|
16
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* A node's own options, its user layer or the default options changed: every resolved result built before is
|
|
19
|
+
* stale.
|
|
20
|
+
*/
|
|
17
21
|
@JvmStatic
|
|
18
22
|
fun optionsChanged() {
|
|
19
23
|
generation++
|
|
@@ -12,25 +12,28 @@ import dev.apexnative.navigation.options.parsers.FractionParser
|
|
|
12
12
|
import dev.apexnative.navigation.options.parsers.TextParser
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* A height a sheet stops at: about half the screen, the full height,
|
|
16
|
-
*
|
|
15
|
+
* A height a sheet stops at: about half the screen, the full height, the height of the screen's content, or a height in
|
|
16
|
+
* dp.
|
|
17
17
|
*/
|
|
18
18
|
sealed class SheetDetent {
|
|
19
19
|
object Medium : SheetDetent()
|
|
20
20
|
object Large : SheetDetent()
|
|
21
|
+
object Content : SheetDetent()
|
|
21
22
|
data class Height(val dp: Double) : SheetDetent()
|
|
22
23
|
|
|
23
24
|
/** The detent as the app names it, in `sheetDetentChanged`. */
|
|
24
25
|
fun toValue(): Any = when (this) {
|
|
25
26
|
Medium -> "medium"
|
|
26
27
|
Large -> "large"
|
|
28
|
+
Content -> "content"
|
|
27
29
|
is Height -> dp
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
companion object {
|
|
31
33
|
fun parse(value: Any?): SheetDetent? = when (value) {
|
|
32
|
-
"medium"
|
|
34
|
+
"medium" -> Medium
|
|
33
35
|
"large" -> Large
|
|
36
|
+
"content" -> Content
|
|
34
37
|
// A number is a height only when it is finite and positive.
|
|
35
38
|
is Number -> value.toDouble().takeIf { it.isFinite() && it > 0 }?.let { Height(it) }
|
|
36
39
|
else -> null
|
|
@@ -47,7 +50,7 @@ class SheetOptions {
|
|
|
47
50
|
@JvmField var selectedDetent: SheetDetent? = null
|
|
48
51
|
@JvmField var largestUndimmedDetent: SheetDetent? = null
|
|
49
52
|
/** The options give `largestUndimmedDetent`, `null` included. */
|
|
50
|
-
@JvmField var hasLargestUndimmedDetent = false
|
|
53
|
+
@OptionKey("largestUndimmedDetent") @JvmField var hasLargestUndimmedDetent = false
|
|
51
54
|
@JvmField var grabber: Bool = NullBool()
|
|
52
55
|
@JvmField var expandsOnScroll: Bool = NullBool()
|
|
53
56
|
@JvmField var cornerRadius: Fraction = NullFraction()
|
|
@@ -20,16 +20,18 @@ class SideMenuOptions {
|
|
|
20
20
|
@JvmField var right = SideMenuSideOptions()
|
|
21
21
|
@JvmField var openGestureMode: Text = NullText()
|
|
22
22
|
@JvmField var animationType: Text = NullText()
|
|
23
|
+
@JvmField var menusAttachMode: Text = NullText()
|
|
23
24
|
@JvmField var testID: Text = NullText()
|
|
24
25
|
|
|
25
26
|
fun hasValue(): Boolean = left.hasValue() || right.hasValue() || openGestureMode.hasValue() ||
|
|
26
|
-
animationType.hasValue() || testID.hasValue()
|
|
27
|
+
animationType.hasValue() || menusAttachMode.hasValue() || testID.hasValue()
|
|
27
28
|
|
|
28
29
|
fun mergeWith(other: SideMenuOptions) {
|
|
29
30
|
left.mergeWith(other.left)
|
|
30
31
|
right.mergeWith(other.right)
|
|
31
32
|
if (other.openGestureMode.hasValue()) openGestureMode = other.openGestureMode
|
|
32
33
|
if (other.animationType.hasValue()) animationType = other.animationType
|
|
34
|
+
if (other.menusAttachMode.hasValue()) menusAttachMode = other.menusAttachMode
|
|
33
35
|
if (other.testID.hasValue()) testID = other.testID
|
|
34
36
|
}
|
|
35
37
|
|
|
@@ -38,6 +40,7 @@ class SideMenuOptions {
|
|
|
38
40
|
right.mergeWithDefault(defaults.right)
|
|
39
41
|
if (!openGestureMode.hasValue()) openGestureMode = defaults.openGestureMode
|
|
40
42
|
if (!animationType.hasValue()) animationType = defaults.animationType
|
|
43
|
+
if (!menusAttachMode.hasValue()) menusAttachMode = defaults.menusAttachMode
|
|
41
44
|
if (!testID.hasValue()) testID = defaults.testID
|
|
42
45
|
}
|
|
43
46
|
|
|
@@ -46,6 +49,7 @@ class SideMenuOptions {
|
|
|
46
49
|
companion object {
|
|
47
50
|
private val OPEN_GESTURE_MODES = setOf("bezel", "entireScreen")
|
|
48
51
|
private val ANIMATION_TYPES = setOf("parallax", "slide", "slide-and-scale", "door")
|
|
52
|
+
private val MENUS_ATTACH_MODES = setOf("together", "afterCenter", "onOpen")
|
|
49
53
|
|
|
50
54
|
@JvmStatic
|
|
51
55
|
fun parse(map: ReadableMap?): SideMenuOptions {
|
|
@@ -55,6 +59,7 @@ class SideMenuOptions {
|
|
|
55
59
|
options.right = map.group("right") { SideMenuSideOptions.parse(it) }
|
|
56
60
|
options.openGestureMode = TextParser.parse(map, "openGestureMode", OPEN_GESTURE_MODES)
|
|
57
61
|
options.animationType = TextParser.parse(map, "animationType", ANIMATION_TYPES)
|
|
62
|
+
options.menusAttachMode = TextParser.parse(map, "menusAttachMode", MENUS_ATTACH_MODES)
|
|
58
63
|
options.testID = TextParser.parse(map, "testID")
|
|
59
64
|
return options
|
|
60
65
|
}
|
|
@@ -99,8 +99,8 @@ class BottomTabsEnterExitAnimationOptions {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
/**
|
|
102
|
-
* `StackAnimationOptions`: the
|
|
103
|
-
*
|
|
102
|
+
* `StackAnimationOptions`: the base of the animations of `push`, `pop` and `setStackRoot`; over the shared elements and
|
|
103
|
+
* element transitions of [LayoutAnimation].
|
|
104
104
|
*/
|
|
105
105
|
open class StackAnimationOptions : LayoutAnimation() {
|
|
106
106
|
@JvmField var enabled: Bool = NullBool()
|
|
@@ -188,6 +188,44 @@ class StackPushAnimationOptions : StackAnimationOptions() {
|
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
+
/**
|
|
192
|
+
* `StackPopAnimationOptions`: the animation of `pop`, and `preview`: whether a back gesture over the stack previews the
|
|
193
|
+
* pop of its top (Android 14+); `false` pops it when the gesture is released, as on Android 13.
|
|
194
|
+
*/
|
|
195
|
+
class StackPopAnimationOptions : StackAnimationOptions() {
|
|
196
|
+
@JvmField var preview: Bool = NullBool()
|
|
197
|
+
|
|
198
|
+
override fun hasValue(): Boolean = super.hasValue() || preview.hasValue()
|
|
199
|
+
|
|
200
|
+
fun mergeWith(other: StackPopAnimationOptions) {
|
|
201
|
+
super.mergeWith(other)
|
|
202
|
+
if (other.preview.hasValue()) preview = other.preview
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
fun mergeWithDefault(defaults: StackPopAnimationOptions) {
|
|
206
|
+
super.mergeWithDefault(defaults)
|
|
207
|
+
if (!preview.hasValue()) preview = defaults.preview
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
override fun copy(): StackPopAnimationOptions = StackPopAnimationOptions().also { it.mergeWith(this) }
|
|
211
|
+
|
|
212
|
+
// Reads the fields of this class from [map], after those of its parent.
|
|
213
|
+
private fun readStackPopAnimationOptions(map: ReadableMap) {
|
|
214
|
+
readStackAnimationOptions(map)
|
|
215
|
+
preview = BoolParser.parse(map, "preview")
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
companion object {
|
|
219
|
+
@JvmStatic
|
|
220
|
+
fun parse(map: ReadableMap?): StackPopAnimationOptions {
|
|
221
|
+
val options = StackPopAnimationOptions()
|
|
222
|
+
if (map == null) return options
|
|
223
|
+
options.readStackPopAnimationOptions(map)
|
|
224
|
+
return options
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
191
229
|
/** `SetStackRootAnimationOptions`: the animation of `setStackRoot`. */
|
|
192
230
|
class SetStackRootAnimationOptions : StackAnimationOptions() {
|
|
193
231
|
@JvmField var asPush: Bool = NullBool()
|
|
@@ -22,9 +22,13 @@ class StatusBarOptions {
|
|
|
22
22
|
@JvmField var hideWithTopBar: Bool = NullBool()
|
|
23
23
|
@JvmField var blur: Bool = NullBool()
|
|
24
24
|
|
|
25
|
-
/**
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
/**
|
|
26
|
+
* The status bar is hidden, or the screen is drawn under it: the screen keeps no room for it. Without `drawBehind`, a
|
|
27
|
+
* screen or a layout in an overlay ([inOverlay]) is drawn under it: an overlay covers the whole window, its dimmed
|
|
28
|
+
* backdrop the status bar too.
|
|
29
|
+
*/
|
|
30
|
+
fun isHiddenOrDrawBehind(inOverlay: Boolean): Boolean =
|
|
31
|
+
visible.isFalse || if (drawBehind.hasValue()) drawBehind.isTrue else inOverlay
|
|
28
32
|
|
|
29
33
|
fun hasValue(): Boolean = visible.hasValue() || style.hasValue() || backgroundColor.hasValue() ||
|
|
30
34
|
drawBehind.hasValue() || translucent.hasValue() || animate.hasValue() || hideWithTopBar.hasValue() ||
|
|
@@ -22,7 +22,7 @@ class TitleOptions {
|
|
|
22
22
|
@JvmField var text: Text = NullText()
|
|
23
23
|
@JvmField var fontSize: Fraction = NullFraction()
|
|
24
24
|
@JvmField var color: ThemeColour = NullThemeColour()
|
|
25
|
-
@JvmField var font = FontOptions()
|
|
25
|
+
@ReadFromParent @JvmField var font = FontOptions()
|
|
26
26
|
@JvmField var component = TitleComponentOptions()
|
|
27
27
|
/** Shared between copies, as its module wants. */
|
|
28
28
|
@JvmField var menu: ButtonMenuOptions? = null
|
|
@@ -98,7 +98,7 @@ class SubtitleOptions {
|
|
|
98
98
|
@JvmField var text: Text = NullText()
|
|
99
99
|
@JvmField var fontSize: Fraction = NullFraction()
|
|
100
100
|
@JvmField var color: ThemeColour = NullThemeColour()
|
|
101
|
-
@JvmField var font = FontOptions()
|
|
101
|
+
@ReadFromParent @JvmField var font = FontOptions()
|
|
102
102
|
@JvmField var alignment: Text = NullText()
|
|
103
103
|
|
|
104
104
|
fun hasValue(): Boolean =
|
|
@@ -109,7 +109,7 @@ class TopBarBackgroundOptions {
|
|
|
109
109
|
*/
|
|
110
110
|
class ScrollEdgeAppearanceTitleOptions {
|
|
111
111
|
@JvmField var color: ThemeColour = NullThemeColour()
|
|
112
|
-
@JvmField var font = FontOptions()
|
|
112
|
+
@ReadFromParent @JvmField var font = FontOptions()
|
|
113
113
|
@JvmField var fontSize: Fraction = NullFraction()
|
|
114
114
|
|
|
115
115
|
fun hasValue(): Boolean = color.hasValue() || font.hasValue() || fontSize.hasValue()
|
|
@@ -34,12 +34,14 @@ class TopBarOptions {
|
|
|
34
34
|
@JvmField var rightButtonDisabledColor: ThemeColour = NullThemeColour()
|
|
35
35
|
@JvmField var centerButtonColor: ThemeColour = NullThemeColour()
|
|
36
36
|
@JvmField var centerButtonDisabledColor: ThemeColour = NullThemeColour()
|
|
37
|
+
@JvmField var menuBackgroundColor: ThemeColour = NullThemeColour()
|
|
38
|
+
@JvmField var menuTextColor: ThemeColour = NullThemeColour()
|
|
37
39
|
@JvmField var drawBehind: Bool = NullBool()
|
|
38
40
|
@JvmField var testID: Text = NullText()
|
|
39
41
|
@JvmField var title = TitleOptions()
|
|
40
42
|
@JvmField var subtitle = SubtitleOptions()
|
|
41
43
|
/** `backButton`, `leftButtons`, `rightButtons`, `centerButtons`. */
|
|
42
|
-
@JvmField var buttons = TopBarButtons()
|
|
44
|
+
@ReadFromParent @JvmField var buttons = TopBarButtons()
|
|
43
45
|
@JvmField var customizationId: Text = NullText()
|
|
44
46
|
/** Shared between copies, as its module wants. */
|
|
45
47
|
@JvmField var overflowMenu: ButtonMenuOptions? = null
|
|
@@ -63,7 +65,8 @@ class TopBarOptions {
|
|
|
63
65
|
hideOnTap.hasValue() || hideOnKeyboard.hasValue() || leftButtonColor.hasValue() ||
|
|
64
66
|
rightButtonColor.hasValue() || leftButtonBackgroundColor.hasValue() || rightButtonBackgroundColor.hasValue() ||
|
|
65
67
|
leftButtonDisabledColor.hasValue() || rightButtonDisabledColor.hasValue() || centerButtonColor.hasValue() ||
|
|
66
|
-
centerButtonDisabledColor.hasValue() ||
|
|
68
|
+
centerButtonDisabledColor.hasValue() || menuBackgroundColor.hasValue() || menuTextColor.hasValue() ||
|
|
69
|
+
drawBehind.hasValue() || testID.hasValue() || title.hasValue() ||
|
|
67
70
|
subtitle.hasValue() || buttons.hasValue() || customizationId.hasValue() || overflowMenu != null ||
|
|
68
71
|
verticalBarKeeps.hasValue() || background.hasValue() || scrollEdgeAppearance.hasValue() ||
|
|
69
72
|
barStyle.hasValue() || style.hasValue() || noBorder.hasValue() || searchBar.hasAnyValue() ||
|
|
@@ -85,6 +88,8 @@ class TopBarOptions {
|
|
|
85
88
|
rightButtonDisabledColor = rightButtonDisabledColor.mergeWith(other.rightButtonDisabledColor)
|
|
86
89
|
centerButtonColor = centerButtonColor.mergeWith(other.centerButtonColor)
|
|
87
90
|
centerButtonDisabledColor = centerButtonDisabledColor.mergeWith(other.centerButtonDisabledColor)
|
|
91
|
+
menuBackgroundColor = menuBackgroundColor.mergeWith(other.menuBackgroundColor)
|
|
92
|
+
menuTextColor = menuTextColor.mergeWith(other.menuTextColor)
|
|
88
93
|
if (other.drawBehind.hasValue()) drawBehind = other.drawBehind
|
|
89
94
|
if (other.testID.hasValue()) testID = other.testID
|
|
90
95
|
title.mergeWith(other.title)
|
|
@@ -127,6 +132,8 @@ class TopBarOptions {
|
|
|
127
132
|
rightButtonDisabledColor = rightButtonDisabledColor.withDefault(defaults.rightButtonDisabledColor)
|
|
128
133
|
centerButtonColor = centerButtonColor.withDefault(defaults.centerButtonColor)
|
|
129
134
|
centerButtonDisabledColor = centerButtonDisabledColor.withDefault(defaults.centerButtonDisabledColor)
|
|
135
|
+
menuBackgroundColor = menuBackgroundColor.withDefault(defaults.menuBackgroundColor)
|
|
136
|
+
menuTextColor = menuTextColor.withDefault(defaults.menuTextColor)
|
|
130
137
|
if (!drawBehind.hasValue()) drawBehind = defaults.drawBehind
|
|
131
138
|
if (!testID.hasValue()) testID = defaults.testID
|
|
132
139
|
title.mergeWithDefault(defaults.title)
|
|
@@ -178,6 +185,8 @@ class TopBarOptions {
|
|
|
178
185
|
options.rightButtonDisabledColor = ThemeColour.parse(context, map, "rightButtonDisabledColor")
|
|
179
186
|
options.centerButtonColor = ThemeColour.parse(context, map, "centerButtonColor")
|
|
180
187
|
options.centerButtonDisabledColor = ThemeColour.parse(context, map, "centerButtonDisabledColor")
|
|
188
|
+
options.menuBackgroundColor = ThemeColour.parse(context, map, "menuBackgroundColor")
|
|
189
|
+
options.menuTextColor = ThemeColour.parse(context, map, "menuTextColor")
|
|
181
190
|
options.drawBehind = BoolParser.parse(map, "drawBehind")
|
|
182
191
|
options.testID = TextParser.parse(map, "testID")
|
|
183
192
|
options.title = map.group("title") { TitleOptions.parse(context, it) }
|
|
@@ -212,13 +221,13 @@ class TopBarOptions {
|
|
|
212
221
|
* don't give it; `[]` takes the buttons of the layers below away.
|
|
213
222
|
*/
|
|
214
223
|
class TopBarButtons {
|
|
215
|
-
@JvmField var back = BackButtonOptions()
|
|
224
|
+
@OptionKey("backButton") @JvmField var back = BackButtonOptions()
|
|
216
225
|
/** `topBar.leftButtons`; null when the options don't give them. */
|
|
217
|
-
@JvmField var left: List<ButtonOptions>? = null
|
|
226
|
+
@OptionKey("leftButtons") @JvmField var left: List<ButtonOptions>? = null
|
|
218
227
|
/** `topBar.rightButtons`; null when the options don't give them. */
|
|
219
|
-
@JvmField var right: List<ButtonOptions>? = null
|
|
228
|
+
@OptionKey("rightButtons") @JvmField var right: List<ButtonOptions>? = null
|
|
220
229
|
/** `topBar.centerButtons`; null when the options don't give them. */
|
|
221
|
-
@JvmField var center: List<ButtonOptions>? = null
|
|
230
|
+
@OptionKey("centerButtons") @JvmField var center: List<ButtonOptions>? = null
|
|
222
231
|
|
|
223
232
|
fun hasValue(): Boolean = back.hasValue() || left != null || right != null || center != null
|
|
224
233
|
|
|
@@ -263,7 +272,7 @@ class BackButtonOptions {
|
|
|
263
272
|
@JvmField var showTitle: Bool = NullBool()
|
|
264
273
|
@JvmField var color: ThemeColour = NullThemeColour()
|
|
265
274
|
@JvmField var fontSize: Fraction = NullFraction()
|
|
266
|
-
@JvmField var font = FontOptions()
|
|
275
|
+
@ReadFromParent @JvmField var font = FontOptions()
|
|
267
276
|
@JvmField var iconBackground = IconBackgroundOptions()
|
|
268
277
|
@JvmField var testID: Text = NullText()
|
|
269
278
|
@JvmField var enableMenu: Bool = NullBool()
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
package dev.apexnative.navigation.options
|
|
2
|
+
|
|
3
|
+
import dev.apexnative.navigation.options.params.Text
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The user layer of a node: what the user chose in the native UI, kept apart from the node's own options so that the
|
|
7
|
+
* app's next `mergeOptions` or `setDefaultOptions` doesn't wipe it. The choices are the check of a single-selection
|
|
8
|
+
* menu (a bar button's `menu`, by the button's id; `topBar.overflowMenu`) and the search scope
|
|
9
|
+
* (`topBar.searchBar.selectedScope`).
|
|
10
|
+
*
|
|
11
|
+
* It goes over everything else as the node's options resolve (defaults < parents < own < user), by identity rather
|
|
12
|
+
* than as a tree merged over: a menu's check by the button's id and the item's id, the scope by its id. A choice whose
|
|
13
|
+
* button, item or scope is gone is not applied, and leaves at the node's next merge; a merge that gives a chosen field
|
|
14
|
+
* a value other than the one the app had there before takes the choice away ([yieldTo]). `setDefaultOptions` never
|
|
15
|
+
* clears it. The node owns it and writes it through `ViewController.changeChoices`, which moves [OptionsCache]. Main
|
|
16
|
+
* thread only.
|
|
17
|
+
*/
|
|
18
|
+
internal class UserChoices {
|
|
19
|
+
// The menus' checks: per menu (a button's id, OVERFLOW for `overflowMenu`) the item picked in each of its levels,
|
|
20
|
+
// in the order of the picks.
|
|
21
|
+
private val checks = LinkedHashMap<String, MutableList<String>>()
|
|
22
|
+
private var scope: String? = null
|
|
23
|
+
|
|
24
|
+
/** The user chose nothing that stays. */
|
|
25
|
+
val isEmpty: Boolean
|
|
26
|
+
get() = checks.isEmpty() && scope == null
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The user picked [itemId] in [menu], the menu of the button [buttonId] or `overflowMenu` (null), as it showed: it
|
|
30
|
+
* takes the place of an earlier pick in the same level.
|
|
31
|
+
*/
|
|
32
|
+
fun check(buttonId: String?, menu: ButtonMenuOptions, itemId: String) {
|
|
33
|
+
val picks = checks.getOrPut(keyOf(buttonId)) { mutableListOf() }
|
|
34
|
+
val level = levelItems(menu.items, itemId)?.map { it.id }.orEmpty()
|
|
35
|
+
picks.removeAll { it == itemId || it in level }
|
|
36
|
+
picks += itemId
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** The user picked the search scope [scopeId]. */
|
|
40
|
+
fun pickScope(scopeId: String) {
|
|
41
|
+
scope = scopeId
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Writes the choices into [resolved], a result of resolution nobody else holds yet; the menus it changes are copied
|
|
46
|
+
* first, as a resolved result shares its menus with the layers they come from. Returns [resolved].
|
|
47
|
+
*/
|
|
48
|
+
fun applyTo(resolved: Options): Options {
|
|
49
|
+
if (isEmpty) return resolved
|
|
50
|
+
val topBar = resolved.topBar
|
|
51
|
+
for ((key, picks) in checks) {
|
|
52
|
+
if (key == OVERFLOW) {
|
|
53
|
+
val menu = topBar.overflowMenu ?: continue
|
|
54
|
+
topBar.overflowMenu = menu.copyMenu().also { copy -> picks.forEach { mark(copy, it) } }
|
|
55
|
+
continue
|
|
56
|
+
}
|
|
57
|
+
val button = buttonIn(topBar.buttons, key) ?: continue
|
|
58
|
+
val menu = button.menu ?: continue
|
|
59
|
+
button.menu = menu.copyMenu().also { copy -> picks.forEach { mark(copy, it) } }
|
|
60
|
+
}
|
|
61
|
+
scope?.let { picked ->
|
|
62
|
+
val searchBar = topBar.searchBar
|
|
63
|
+
if (searchBar.scopes?.any { it.id == picked } == true) searchBar.selectedScope = Text(picked)
|
|
64
|
+
}
|
|
65
|
+
return resolved
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The app merged [delta] into the node. A choice leaves when what it was made in is gone from [after] (the node's
|
|
70
|
+
* options as they resolve after the merge, without this layer), or when [delta] gives its field a value other than
|
|
71
|
+
* the one the node's own options had before the merge ([own]; where they had none, the app's resolution before the
|
|
72
|
+
* merge, [before]). The same value sent again (a re-render) keeps the choice. Returns whether a choice left.
|
|
73
|
+
*/
|
|
74
|
+
fun yieldTo(delta: Options, own: Options, before: Options, after: Options): Boolean {
|
|
75
|
+
var changed = false
|
|
76
|
+
val entries = checks.entries.iterator()
|
|
77
|
+
while (entries.hasNext()) {
|
|
78
|
+
val (key, picks) = entries.next()
|
|
79
|
+
val now = menuIn(after, key)
|
|
80
|
+
val given = menuIn(delta, key)
|
|
81
|
+
val was = menuIn(own, key) ?: menuIn(before, key)
|
|
82
|
+
val left = picks.removeAll { itemId ->
|
|
83
|
+
val gone = now == null || levelItems(now.items, itemId) == null
|
|
84
|
+
gone || (given != null && checkedInLevel(given, itemId) != was?.let { checkedInLevel(it, itemId) })
|
|
85
|
+
}
|
|
86
|
+
if (left) changed = true
|
|
87
|
+
if (picks.isEmpty()) entries.remove()
|
|
88
|
+
}
|
|
89
|
+
scope?.let { picked ->
|
|
90
|
+
val given = delta.topBar.searchBar.selectedScope
|
|
91
|
+
val ownScope = own.topBar.searchBar.selectedScope
|
|
92
|
+
val was = (if (ownScope.hasValue()) ownScope else before.topBar.searchBar.selectedScope).get(null)
|
|
93
|
+
val changedByApp = given.hasValue() && given.get(null) != was
|
|
94
|
+
val gone = after.topBar.searchBar.scopes?.any { it.id == picked } != true
|
|
95
|
+
if (changedByApp || gone) {
|
|
96
|
+
scope = null
|
|
97
|
+
changed = true
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return changed
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
companion object {
|
|
104
|
+
// The key of `overflowMenu`, which has no button; no placed button has an empty id.
|
|
105
|
+
private const val OVERFLOW = ""
|
|
106
|
+
|
|
107
|
+
private fun keyOf(buttonId: String?): String = buttonId ?: OVERFLOW
|
|
108
|
+
|
|
109
|
+
/** Whether picking [itemId] in [menu] moves a check: its level has `singleSelection`. */
|
|
110
|
+
fun checks(menu: ButtonMenuOptions, itemId: String): Boolean =
|
|
111
|
+
levelOf(menu.items, menu.singleSelection, itemId) == true
|
|
112
|
+
|
|
113
|
+
/** Moves the check of [itemId]'s level to it, in [menu] itself; nothing in a level without single selection. */
|
|
114
|
+
fun mark(menu: ButtonMenuOptions, itemId: String) {
|
|
115
|
+
mark(menu.items, menu.singleSelection, itemId)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private fun buttonIn(buttons: TopBarButtons, id: String): ButtonOptions? =
|
|
119
|
+
buttons.left?.firstOrNull { it.id.get(null) == id } ?: buttons.right?.firstOrNull { it.id.get(null) == id }
|
|
120
|
+
|
|
121
|
+
// The menu the key names in [options]: `overflowMenu`, or the menu of the button with that id.
|
|
122
|
+
private fun menuIn(options: Options, key: String): ButtonMenuOptions? =
|
|
123
|
+
if (key == OVERFLOW) options.topBar.overflowMenu else buttonIn(options.topBar.buttons, key)?.menu
|
|
124
|
+
|
|
125
|
+
// The checked items of the level that holds [itemId] in [menu]: the field a merge gives that level.
|
|
126
|
+
private fun checkedInLevel(menu: ButtonMenuOptions, itemId: String): Set<String>? =
|
|
127
|
+
levelItems(menu.items, itemId)?.filter { it.checked }?.map { it.id }?.toSet()
|
|
128
|
+
|
|
129
|
+
// The items of the level that holds [itemId]; null when it isn't in [elements].
|
|
130
|
+
private fun levelItems(
|
|
131
|
+
elements: List<ButtonMenuOptions.Element>,
|
|
132
|
+
itemId: String,
|
|
133
|
+
): List<ButtonMenuOptions.Item>? {
|
|
134
|
+
val items = elements.filterIsInstance<ButtonMenuOptions.Item>()
|
|
135
|
+
if (items.any { it.id == itemId }) return items
|
|
136
|
+
return elements.filterIsInstance<ButtonMenuOptions.Submenu>().firstNotNullOfOrNull {
|
|
137
|
+
levelItems(it.items, itemId)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Whether the level holding [itemId] has single selection; null when [itemId] isn't in [elements].
|
|
142
|
+
private fun levelOf(elements: List<ButtonMenuOptions.Element>, single: Boolean, itemId: String): Boolean? {
|
|
143
|
+
if (elements.any { it is ButtonMenuOptions.Item && it.id == itemId }) return single
|
|
144
|
+
for (element in elements) {
|
|
145
|
+
if (element !is ButtonMenuOptions.Submenu) continue
|
|
146
|
+
levelOf(element.items, element.singleSelection, itemId)?.let { return it }
|
|
147
|
+
}
|
|
148
|
+
return null
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private fun mark(elements: List<ButtonMenuOptions.Element>, single: Boolean, itemId: String): Boolean {
|
|
152
|
+
if (elements.any { it is ButtonMenuOptions.Item && it.id == itemId }) {
|
|
153
|
+
if (single) elements.forEach { if (it is ButtonMenuOptions.Item) it.checked = it.id == itemId }
|
|
154
|
+
return true
|
|
155
|
+
}
|
|
156
|
+
return elements.any { it is ButtonMenuOptions.Submenu && mark(it.items, it.singleSelection, itemId) }
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|