@apexnative/navigation 1.0.0-alpha.1 → 1.0.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (573) hide show
  1. package/ApexNavigation.podspec +2 -1
  2. package/CHANGELOG.md +120 -0
  3. package/README.md +147 -51
  4. package/android/CLAUDE.md +78 -25
  5. package/android/CORE.md +49 -25
  6. package/android/RECIPES.md +13 -6
  7. package/android/consumer-rules.pro +6 -0
  8. package/android/src/main/java/dev/apexnative/navigation/NavigationActivity.kt +85 -10
  9. package/android/src/main/java/dev/apexnative/navigation/NavigationApplication.kt +34 -13
  10. package/android/src/main/java/dev/apexnative/navigation/layout/LayoutChecks.kt +5 -1
  11. package/android/src/main/java/dev/apexnative/navigation/layout/LayoutNode.kt +6 -2
  12. package/android/src/main/java/dev/apexnative/navigation/nativescreen/NativeScreenContext.kt +2 -2
  13. package/android/src/main/java/dev/apexnative/navigation/options/AnimationsOptions.kt +2 -2
  14. package/android/src/main/java/dev/apexnative/navigation/options/BottomTabOptions.kt +1 -1
  15. package/android/src/main/java/dev/apexnative/navigation/options/BottomTabsOptions.kt +13 -8
  16. package/android/src/main/java/dev/apexnative/navigation/options/ButtonMenuOptions.kt +2 -2
  17. package/android/src/main/java/dev/apexnative/navigation/options/ButtonOptions.kt +3 -3
  18. package/android/src/main/java/dev/apexnative/navigation/options/HardwareBackButtonOptions.kt +9 -1
  19. package/android/src/main/java/dev/apexnative/navigation/options/LargeTitleOptions.kt +1 -1
  20. package/android/src/main/java/dev/apexnative/navigation/options/LayoutAnimation.kt +1 -1
  21. package/android/src/main/java/dev/apexnative/navigation/options/OptionKey.kt +18 -0
  22. package/android/src/main/java/dev/apexnative/navigation/options/OptionPaths.kt +91 -0
  23. package/android/src/main/java/dev/apexnative/navigation/options/OptionsCache.kt +8 -4
  24. package/android/src/main/java/dev/apexnative/navigation/options/SheetOptions.kt +7 -4
  25. package/android/src/main/java/dev/apexnative/navigation/options/SideMenuOptions.kt +6 -1
  26. package/android/src/main/java/dev/apexnative/navigation/options/StackAnimationOptions.kt +40 -2
  27. package/android/src/main/java/dev/apexnative/navigation/options/StatusBarOptions.kt +7 -3
  28. package/android/src/main/java/dev/apexnative/navigation/options/TitleOptions.kt +2 -2
  29. package/android/src/main/java/dev/apexnative/navigation/options/TopBarAppearanceOptions.kt +1 -1
  30. package/android/src/main/java/dev/apexnative/navigation/options/TopBarOptions.kt +16 -7
  31. package/android/src/main/java/dev/apexnative/navigation/options/UserChoices.kt +159 -0
  32. package/android/src/main/java/dev/apexnative/navigation/react/CommandAnswer.kt +29 -36
  33. package/android/src/main/java/dev/apexnative/navigation/react/CommandContract.kt +59 -0
  34. package/android/src/main/java/dev/apexnative/navigation/react/ContentHeights.kt +95 -0
  35. package/android/src/main/java/dev/apexnative/navigation/react/ContentMounts.kt +66 -0
  36. package/android/src/main/java/dev/apexnative/navigation/react/ErrorTexts.kt +75 -60
  37. package/android/src/main/java/dev/apexnative/navigation/react/Hinge.kt +35 -23
  38. package/android/src/main/java/dev/apexnative/navigation/react/NavigationTurboModule.kt +12 -7
  39. package/android/src/main/java/dev/apexnative/navigation/react/OptionsCommands.kt +42 -4
  40. package/android/src/main/java/dev/apexnative/navigation/react/PendingCalls.kt +48 -0
  41. package/android/src/main/java/dev/apexnative/navigation/react/ReactView.kt +54 -20
  42. package/android/src/main/java/dev/apexnative/navigation/react/ReloadCoordinator.kt +7 -6
  43. package/android/src/main/java/dev/apexnative/navigation/react/ScreenEnvironment.kt +177 -0
  44. package/android/src/main/java/dev/apexnative/navigation/react/ScreenRegions.kt +19 -50
  45. package/android/src/main/java/dev/apexnative/navigation/react/ScrollEvents.kt +49 -128
  46. package/android/src/main/java/dev/apexnative/navigation/react/events/AppearanceDispatcher.kt +50 -81
  47. package/android/src/main/java/dev/apexnative/navigation/react/events/EventContract.kt +226 -0
  48. package/android/src/main/java/dev/apexnative/navigation/react/events/EventEmitter.kt +135 -94
  49. package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationState.kt +154 -0
  50. package/android/src/main/java/dev/apexnative/navigation/react/events/ScreenAppearance.kt +0 -6
  51. package/android/src/main/java/dev/apexnative/navigation/safearea/SafeAreaView.kt +12 -10
  52. package/android/src/main/java/dev/apexnative/navigation/slots/SlotContainers.kt +10 -7
  53. package/android/src/main/java/dev/apexnative/navigation/slots/SlotScreenView.kt +39 -19
  54. package/android/src/main/java/dev/apexnative/navigation/slots/SlotView.kt +16 -4
  55. package/android/src/main/java/dev/apexnative/navigation/slots/SlotViews.kt +40 -0
  56. package/android/src/main/java/dev/apexnative/navigation/utils/ImageKey.kt +66 -0
  57. package/android/src/main/java/dev/apexnative/navigation/utils/ImageLoader.kt +7 -89
  58. package/android/src/main/java/dev/apexnative/navigation/utils/ImageRequests.kt +76 -0
  59. package/android/src/main/java/dev/apexnative/navigation/utils/MaterialTheme.kt +5 -6
  60. package/android/src/main/java/dev/apexnative/navigation/utils/OptionImages.kt +262 -0
  61. package/android/src/main/java/dev/apexnative/navigation/utils/SystemAnimations.kt +36 -0
  62. package/android/src/main/java/dev/apexnative/navigation/utils/UiUtils.kt +3 -3
  63. package/android/src/main/java/dev/apexnative/navigation/utils/ViewController.kt +3 -1
  64. package/android/src/main/java/dev/apexnative/navigation/utils/ViewExtensions.kt +0 -13
  65. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementController.kt +10 -7
  66. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/SecondaryScreenPresenter.kt +13 -5
  67. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/AppliedTabCalls.kt +49 -0
  68. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsCollapseBehavior.kt +5 -3
  69. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsController.kt +108 -34
  70. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsPresenter.kt +25 -24
  71. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowGeometry.kt +22 -0
  72. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabItems.kt +3 -3
  73. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabsRoom.kt +0 -5
  74. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentPresenter.kt +28 -7
  75. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentViewController.kt +12 -9
  76. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ContentReadiness.kt +2 -2
  77. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/RenderWait.kt +27 -7
  78. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenFrame.kt +1 -1
  79. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenReadiness.kt +103 -56
  80. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenSafeArea.kt +29 -11
  81. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/externalcomponent/ExternalComponentViewController.kt +2 -6
  82. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalAnimations.kt +22 -24
  83. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalCoordinator.kt +109 -21
  84. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalRecord.kt +21 -6
  85. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalSheet.kt +476 -73
  86. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalViews.kt +57 -25
  87. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetBack.kt +42 -0
  88. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetStops.kt +83 -0
  89. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackCheck.kt +50 -0
  90. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackState.kt +49 -14
  91. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/Navigator.kt +71 -12
  92. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/RootCoordinator.kt +37 -11
  93. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/overlay/OverlayCoordinator.kt +10 -8
  94. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/Capabilities.kt +11 -4
  95. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ContainerBackground.kt +3 -3
  96. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ParentController.kt +6 -6
  97. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuController.kt +42 -9
  98. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuMotion.kt +19 -8
  99. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuPresenter.kt +16 -7
  100. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuRules.kt +43 -4
  101. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitPanes.kt +23 -0
  102. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitViewController.kt +77 -17
  103. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/BackPreview.kt +315 -0
  104. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/PreparedFrame.kt +3 -3
  105. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackCommands.kt +30 -20
  106. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackController.kt +216 -18
  107. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackDisplay.kt +26 -1
  108. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackQueue.kt +149 -41
  109. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackTransitions.kt +26 -8
  110. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackViews.kt +115 -6
  111. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabMotion.kt +142 -0
  112. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabPresenter.kt +222 -48
  113. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/ScreenSearch.kt +3 -5
  114. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/StackSearchPresenter.kt +30 -34
  115. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarComponents.kt +5 -51
  116. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarRowTransition.kt +3 -2
  117. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/ButtonPlaces.kt +11 -5
  118. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/MenuChecks.kt +13 -56
  119. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarPresenter.kt +219 -54
  120. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarVisibility.kt +9 -2
  121. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ScrollEventListener.kt +6 -9
  122. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ViewController.kt +75 -21
  123. package/android/src/main/java/dev/apexnative/navigation/views/animations/AnimationLayer.kt +73 -0
  124. package/android/src/main/java/dev/apexnative/navigation/views/animations/Curves.kt +29 -11
  125. package/android/src/main/java/dev/apexnative/navigation/views/animations/ValueInterpolation.kt +14 -0
  126. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabs.kt +9 -7
  127. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabsLayout.kt +61 -2
  128. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomBottomTabItemView.kt +0 -5
  129. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomTabRow.kt +72 -10
  130. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStep.kt +31 -0
  131. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementTransitions.kt +143 -135
  132. package/android/src/main/java/dev/apexnative/navigation/views/element/TargetsWait.kt +13 -5
  133. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionLayer.kt +37 -112
  134. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionTargets.kt +9 -6
  135. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionViews.kt +100 -0
  136. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ElementPictures.kt +112 -4
  137. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/FlightGeometry.kt +346 -36
  138. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMorph.kt +199 -0
  139. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/SharedAnimatorFactory.kt +56 -41
  140. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextMorph.kt +176 -0
  141. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewMorph.kt +108 -0
  142. package/android/src/main/java/dev/apexnative/navigation/views/sidemenu/SideMenuView.kt +12 -3
  143. package/android/src/main/java/dev/apexnative/navigation/views/stack/ScreenEdge.kt +45 -0
  144. package/android/src/main/java/dev/apexnative/navigation/views/stack/StackLayout.kt +140 -1
  145. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/Fab.kt +14 -10
  146. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabCopy.kt +85 -0
  147. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabMenu.kt +13 -0
  148. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TitleBar.kt +5 -17
  149. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TopBar.kt +73 -34
  150. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonComponentCell.kt +6 -6
  151. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonView.kt +113 -0
  152. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarMenu.kt +219 -0
  153. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonBar.kt +125 -178
  154. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonMenus.kt +34 -64
  155. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonRow.kt +216 -0
  156. package/android/src/main/jni/ANNContentHeights.cpp +82 -0
  157. package/android/src/main/res/drawable/apex_navigation_ic_arrow_right.xml +14 -0
  158. package/android/src/main/res/layout/apex_navigation_menu_header.xml +19 -0
  159. package/android/src/main/res/layout/apex_navigation_menu_item.xml +68 -0
  160. package/android/src/main/res/values/styles.xml +1 -1
  161. package/android/src/main/res/values-night/styles.xml +1 -1
  162. package/cli/app.js +1 -1
  163. package/cli/doctor/checks/app.js +77 -14
  164. package/cli/doctor/checks/splash.js +4 -22
  165. package/cli/migrate/native.js +18 -0
  166. package/cli/project.js +10 -2
  167. package/cli/setup/index.js +18 -0
  168. package/cli/setup/source.js +2 -1
  169. package/cli/setup/steps/appDelegate.js +66 -11
  170. package/cli/setup/steps/mainApplication.js +134 -19
  171. package/cli/setup/steps/metro.js +46 -0
  172. package/cli/setup/steps/sceneDelegate.js +108 -0
  173. package/cli/splash/index.js +3 -1
  174. package/docs-md/architecture/native-screens.md +4 -0
  175. package/docs-md/architecture/theme-and-context.md +131 -12
  176. package/docs-md/architecture/transitions.md +58 -12
  177. package/docs-md/containers/modals.md +8 -4
  178. package/docs-md/containers/overlays.md +3 -1
  179. package/docs-md/containers/side-menu.md +19 -2
  180. package/docs-md/containers/tabs.md +5 -1
  181. package/docs-md/flows/bottom-sheets.md +4 -2
  182. package/docs-md/flows/forms-in-a-modal.md +1 -1
  183. package/docs-md/fundamentals/screens-and-props.md +9 -1
  184. package/docs-md/fundamentals/starting-the-app.md +1 -1
  185. package/docs-md/guides/cli.md +4 -3
  186. package/docs-md/guides/deep-links.md +15 -33
  187. package/docs-md/help/glossary.md +4 -4
  188. package/docs-md/help/troubleshooting.md +44 -6
  189. package/docs-md/index.json +57 -1
  190. package/docs-md/migration/from-expo-router.md +1 -1
  191. package/docs-md/migration/from-react-native-navigation.md +9 -3
  192. package/docs-md/migration/from-react-navigation.md +2 -2
  193. package/docs-md/screen-ui/back-and-gestures.md +46 -2
  194. package/docs-md/screen-ui/bar-buttons.md +5 -5
  195. package/docs-md/screen-ui/search.md +1 -1
  196. package/docs-md/screen-ui/system-ui.md +17 -12
  197. package/docs-md/screen-ui/toolbar-and-fab.md +4 -2
  198. package/docs-md/screen-ui/top-bar.md +8 -4
  199. package/docs-md/start/installation.md +21 -3
  200. package/ios/Animations/ANNFrameDriver.h +55 -15
  201. package/ios/Animations/ANNFrameDriver.mm +216 -60
  202. package/ios/Animations/ANNTransitionAnimator.h +26 -5
  203. package/ios/Animations/ANNTransitionAnimator.mm +61 -13
  204. package/ios/Animations/ANNTransitionPlan.h +2 -2
  205. package/ios/Animations/ANNTransitionPlan.mm +10 -0
  206. package/ios/Animations/ANNTransitionWait.mm +6 -7
  207. package/ios/Animations/Elements/ANNElementFinder.h +57 -0
  208. package/ios/Animations/Elements/ANNElementFinder.mm +174 -2
  209. package/ios/Animations/Elements/ANNElementTransition.h +10 -8
  210. package/ios/Animations/Elements/ANNElementTransition.mm +19 -21
  211. package/ios/Animations/Elements/ANNSharedElementFlight.h +16 -11
  212. package/ios/Animations/Elements/ANNSharedElementFlight.mm +308 -69
  213. package/ios/Animations/Interpolators/ANNInterpolate.h +2 -30
  214. package/ios/Animations/Interpolators/ANNTransformParts.h +48 -0
  215. package/ios/Animations/Interpolators/ANNTransformParts.mm +507 -0
  216. package/ios/Animations/Interpolators/ANNViewTracks.h +9 -6
  217. package/ios/Animations/Interpolators/ANNViewTracks.mm +100 -30
  218. package/ios/CLAUDE.md +60 -24
  219. package/ios/CORE.md +44 -34
  220. package/ios/Contract/ANNCommandAnswer.h +13 -5
  221. package/ios/Contract/ANNCommandAnswer.mm +40 -32
  222. package/ios/Contract/ANNCommandContract.h +15 -0
  223. package/ios/Contract/ANNCommandContract.mm +78 -0
  224. package/ios/Contract/ANNCommandRunner.h +10 -9
  225. package/ios/Contract/ANNCommandRunner.mm +22 -28
  226. package/ios/Contract/ANNErrorTexts.h +6 -2
  227. package/ios/Contract/ANNErrorTexts.mm +18 -10
  228. package/ios/Contract/ANNLayoutNode.h +3 -3
  229. package/ios/Contract/ANNLayoutReader.h +3 -3
  230. package/ios/Core/ANNAppDelegate.mm +0 -2
  231. package/ios/Core/ANNAppearanceDispatcher.h +5 -4
  232. package/ios/Core/ANNAppearanceDispatcher.mm +12 -1
  233. package/ios/Core/ANNDeepLinkQueue.h +22 -2
  234. package/ios/Core/ANNDeepLinkQueue.mm +121 -14
  235. package/ios/Core/ANNErrorHandler.h +9 -4
  236. package/ios/Core/ANNErrorHandler.mm +20 -2
  237. package/ios/Core/ANNEventContract.h +246 -0
  238. package/ios/Core/ANNEventContract.mm +225 -0
  239. package/ios/Core/ANNEventEmitter.h +6 -2
  240. package/ios/Core/ANNEventEmitter.mm +117 -80
  241. package/ios/Core/ANNHinge.h +6 -0
  242. package/ios/Core/ANNHinge.mm +15 -4
  243. package/ios/Core/ANNJavaScriptCalls.h +33 -0
  244. package/ios/Core/ANNJavaScriptCalls.mm +52 -0
  245. package/ios/Core/ANNLayoutProtocol.h +5 -5
  246. package/ios/Core/ANNNavigationState.h +7 -5
  247. package/ios/Core/ANNNavigationState.mm +8 -7
  248. package/ios/Core/ANNNodeHelper.h +32 -12
  249. package/ios/Core/ANNNodeHelper.mm +100 -3
  250. package/ios/Core/ANNParking.h +5 -4
  251. package/ios/Core/ANNReloadCoordinator.mm +5 -12
  252. package/ios/Core/ANNRenderWait.h +20 -6
  253. package/ios/Core/ANNRenderWait.mm +143 -56
  254. package/ios/Core/ANNSceneDelegate.mm +25 -15
  255. package/ios/Core/ANNSystemUI.h +3 -2
  256. package/ios/Core/ANNSystemUI.mm +7 -0
  257. package/ios/Core/ANNUtils.h +7 -0
  258. package/ios/Core/ANNUtils.mm +10 -0
  259. package/ios/Core/ApexNavigation+Internal.h +1 -1
  260. package/ios/Core/ApexNavigation.mm +7 -6
  261. package/ios/Core/UIViewController+LayoutProtocol.h +9 -2
  262. package/ios/Core/UIViewController+LayoutProtocol.mm +8 -0
  263. package/ios/Layouts/Arrangement/ANNArrangementState.h +2 -17
  264. package/ios/Layouts/Arrangement/ANNArrangementState.mm +0 -38
  265. package/ios/Layouts/Arrangement/ANNArrangementViewController.mm +10 -8
  266. package/ios/Layouts/Modal/ANNModalCoordinator.h +1 -1
  267. package/ios/Layouts/Modal/ANNModalCoordinator.mm +57 -16
  268. package/ios/Layouts/Modal/ANNModalPresentation.h +8 -5
  269. package/ios/Layouts/Modal/ANNModalPresentation.mm +12 -12
  270. package/ios/Layouts/Modal/ANNSheetPresenter.mm +83 -1
  271. package/ios/Layouts/Overlay/ANNOverlayCoordinator.mm +2 -8
  272. package/ios/Layouts/Root/ANNRootCoordinator.mm +58 -19
  273. package/ios/Layouts/Root/ANNSplashViewController.h +5 -3
  274. package/ios/Layouts/Root/ANNSplashViewController.mm +147 -0
  275. package/ios/Layouts/Screen/ANNComponentPresenter.h +11 -3
  276. package/ios/Layouts/Screen/ANNComponentPresenter.mm +34 -6
  277. package/ios/Layouts/Screen/ANNComponentViewController.h +15 -13
  278. package/ios/Layouts/Screen/ANNComponentViewController.mm +130 -75
  279. package/ios/Layouts/Screen/ANNNativeScreenContext.mm +7 -5
  280. package/ios/Layouts/Screen/ANNPreviewInteraction.h +7 -4
  281. package/ios/Layouts/Screen/ANNPreviewInteraction.mm +72 -10
  282. package/ios/Layouts/Screen/ANNScreenEnvironment.h +63 -0
  283. package/ios/Layouts/Screen/ANNScreenEnvironment.mm +181 -0
  284. package/ios/Layouts/Screen/ANNScreenPlace.h +53 -0
  285. package/ios/Layouts/Screen/ANNScreenPlace.mm +205 -0
  286. package/ios/Layouts/Screen/ANNScreenRegions.h +3 -18
  287. package/ios/Layouts/Screen/ANNScreenRegions.mm +9 -44
  288. package/ios/Layouts/Screen/ANNScreenSafeArea.h +4 -9
  289. package/ios/Layouts/Screen/ANNScreenSafeArea.mm +14 -16
  290. package/ios/Layouts/Screen/ANNScreenSettling.h +32 -0
  291. package/ios/Layouts/Screen/ANNScreenSettling.mm +137 -0
  292. package/ios/Layouts/SideMenu/ANNSideMenuTypes.h +8 -0
  293. package/ios/Layouts/SideMenu/ANNSideMenuViewController.mm +83 -14
  294. package/ios/Layouts/SplitView/ANNSplitViewCommands.h +3 -2
  295. package/ios/Layouts/SplitView/ANNSplitViewCommands.mm +105 -39
  296. package/ios/Layouts/SplitView/ANNSplitViewController.mm +7 -8
  297. package/ios/Layouts/Stack/ANNPreviewPush.h +7 -6
  298. package/ios/Layouts/Stack/ANNPreviewPush.mm +142 -27
  299. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.h +11 -2
  300. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.mm +14 -7
  301. package/ios/Layouts/Stack/ANNStackCommands.mm +1 -0
  302. package/ios/Layouts/Stack/ANNStackController.h +8 -0
  303. package/ios/Layouts/Stack/ANNStackController.mm +184 -16
  304. package/ios/Layouts/Stack/ANNStackQueue.h +5 -2
  305. package/ios/Layouts/Stack/ANNStackQueue.mm +56 -43
  306. package/ios/Layouts/Stack/ANNSwipePopInteraction.h +26 -0
  307. package/ios/Layouts/Stack/ANNSwipePopInteraction.mm +185 -0
  308. package/ios/Layouts/Stack/InteractivePopGestureDelegate.mm +28 -4
  309. package/ios/Layouts/Stack/UINavigationController+ANNCommands.h +4 -2
  310. package/ios/Layouts/Stack/UINavigationController+ANNCommands.mm +2 -3
  311. package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.h +4 -0
  312. package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.mm +11 -0
  313. package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.h +12 -1
  314. package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.mm +23 -0
  315. package/ios/Layouts/Tabs/ANNBottomTabsController.h +3 -0
  316. package/ios/Layouts/Tabs/ANNBottomTabsController.mm +237 -57
  317. package/ios/Layouts/Tabs/ANNBottomTabsCustomRow.mm +8 -3
  318. package/ios/Layouts/Tabs/ANNBottomTabsPresenter.h +6 -2
  319. package/ios/Layouts/Tabs/ANNBottomTabsPresenter.mm +232 -43
  320. package/ios/Layouts/Tabs/ANNTabsDesign.h +6 -5
  321. package/ios/Layouts/Tabs/ANNTabsDesign.mm +9 -1
  322. package/ios/Layouts/Tabs/UITabBar+utils.h +5 -5
  323. package/ios/Layouts/Tabs/UITabBar+utils.mm +32 -13
  324. package/ios/Options/ANNAnimationOptions.h +2 -1
  325. package/ios/Options/ANNAnimationOptions.mm +1 -1
  326. package/ios/Options/ANNBottomTabsOptions.h +2 -0
  327. package/ios/Options/ANNBottomTabsOptions.mm +1 -0
  328. package/ios/Options/ANNOptions.h +25 -0
  329. package/ios/Options/ANNOptions.mm +157 -1
  330. package/ios/Options/ANNOptionsCache.h +7 -6
  331. package/ios/Options/ANNOptionsReader.mm +108 -0
  332. package/ios/Options/ANNSearchBarOptions.h +4 -3
  333. package/ios/Options/ANNSheetOptions.h +4 -1
  334. package/ios/Options/ANNSideMenuOptions.h +2 -0
  335. package/ios/Options/ANNSideMenuOptions.mm +2 -0
  336. package/ios/Options/ANNStackPopAnimationOptions.h +13 -0
  337. package/ios/Options/ANNStackPopAnimationOptions.mm +11 -0
  338. package/ios/Options/ANNUserChoice.h +57 -0
  339. package/ios/Options/ANNUserChoice.mm +44 -0
  340. package/ios/Options/Params/ANNImageSource.h +61 -0
  341. package/ios/Options/Params/ANNImageSource.mm +101 -0
  342. package/ios/Options/Params/ANNOptionImages.h +37 -0
  343. package/ios/Options/Params/ANNOptionImages.mm +284 -0
  344. package/ios/Options/Params/ANNParam.h +15 -0
  345. package/ios/Options/Params/ANNParam.mm +61 -0
  346. package/ios/Options/Params/Color.h +3 -0
  347. package/ios/Options/Params/Color.mm +21 -0
  348. package/ios/Options/Params/ColorParser.h +4 -3
  349. package/ios/Options/Params/ColorParser.mm +22 -4
  350. package/ios/Options/Params/Image.h +15 -2
  351. package/ios/Options/Params/Image.mm +35 -2
  352. package/ios/Options/Params/ImageParser.h +5 -5
  353. package/ios/Options/Params/ImageParser.mm +28 -46
  354. package/ios/Public/ApexNavigation/ANNSceneDelegate.h +3 -0
  355. package/ios/Public/ApexNavigation/ApexNavigation.h +1 -1
  356. package/ios/RECIPES.md +13 -6
  357. package/ios/React/ANNReactView.mm +6 -25
  358. package/ios/React/ANNSafeAreaViewComponentView.mm +28 -17
  359. package/ios/React/ANNSurfaceHostingView.h +14 -0
  360. package/ios/React/ANNSurfaceHostingView.mm +144 -1
  361. package/ios/React/Slots/ANNSlotComponentView.mm +24 -17
  362. package/ios/React/Slots/ANNSlotContainers.h +14 -6
  363. package/ios/React/Slots/ANNSlotContainers.mm +75 -2
  364. package/ios/React/Slots/ANNSlotHost.mm +1 -3
  365. package/ios/React/Slots/ANNSlotScreenView.mm +8 -2
  366. package/ios/TopBar/ANNBackButtonPresenter.mm +6 -5
  367. package/ios/TopBar/ANNBarAppearance.h +2 -1
  368. package/ios/TopBar/ANNBarAppearance.mm +111 -30
  369. package/ios/TopBar/ANNBarBackgroundComponent.mm +16 -0
  370. package/ios/TopBar/ANNBarButtonComponentView.h +4 -4
  371. package/ios/TopBar/ANNBarButtonComponentView.mm +1 -1
  372. package/ios/TopBar/ANNBarButtons.h +14 -8
  373. package/ios/TopBar/ANNBarButtons.mm +397 -80
  374. package/ios/TopBar/ANNIconButtonImage.h +1 -0
  375. package/ios/TopBar/ANNIconButtonImage.mm +34 -1
  376. package/ios/TopBar/ANNLargeTitlePresenter.h +13 -0
  377. package/ios/TopBar/ANNLargeTitlePresenter.mm +50 -7
  378. package/ios/TopBar/ANNMainList.h +3 -0
  379. package/ios/TopBar/ANNMainList.mm +4 -0
  380. package/ios/TopBar/ANNScrollEdgeEffects.h +22 -6
  381. package/ios/TopBar/ANNScrollEdgeEffects.mm +123 -16
  382. package/ios/TopBar/ANNSearchPresenter.mm +172 -21
  383. package/ios/TopBar/ANNSearchResultsViewController.mm +29 -6
  384. package/ios/TopBar/ANNTopBarPresenter.h +8 -2
  385. package/ios/TopBar/ANNTopBarPresenter.mm +155 -33
  386. package/ios/TurboModules/ANNTurboEventEmitter.mm +4 -35
  387. package/ios/TurboModules/ANNTurboModule.mm +104 -33
  388. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.cpp +20 -0
  389. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.h +5 -14
  390. package/lib/module/ARCHITECTURE.md +40 -27
  391. package/lib/module/adapters/NativeANNTurboModule.js.map +1 -1
  392. package/lib/module/api/app/AppRegistry.js +14 -2
  393. package/lib/module/api/app/AppRegistry.js.map +1 -1
  394. package/lib/module/api/app/createNavigation.js +190 -66
  395. package/lib/module/api/app/createNavigation.js.map +1 -1
  396. package/lib/module/api/commands/commands.js +54 -6
  397. package/lib/module/api/commands/commands.js.map +1 -1
  398. package/lib/module/api/events/navigationEvents.js +6 -2
  399. package/lib/module/api/events/navigationEvents.js.map +1 -1
  400. package/lib/module/api/hooks/useNavigation.js +8 -3
  401. package/lib/module/api/hooks/useNavigation.js.map +1 -1
  402. package/lib/module/api/hooks/useSafeAreaInsets.js +4 -3
  403. package/lib/module/api/hooks/useSafeAreaInsets.js.map +1 -1
  404. package/lib/module/api/linking/dispatchedLinks.js +23 -0
  405. package/lib/module/api/linking/dispatchedLinks.js.map +1 -0
  406. package/lib/module/api/linking/linking.js +11 -0
  407. package/lib/module/api/linking/linking.js.map +1 -1
  408. package/lib/module/api/navigation.js.map +1 -1
  409. package/lib/module/api/options/OptionsChain.js +2 -2
  410. package/lib/module/api/screens/defineScreen.js +45 -3
  411. package/lib/module/api/screens/defineScreen.js.map +1 -1
  412. package/lib/module/api/screens/nativeScreens.js +31 -6
  413. package/lib/module/api/screens/nativeScreens.js.map +1 -1
  414. package/lib/module/api/screens/registerScreens.js +193 -35
  415. package/lib/module/api/screens/registerScreens.js.map +1 -1
  416. package/lib/module/api/theme/theme.js +5 -0
  417. package/lib/module/api/theme/theme.js.map +1 -1
  418. package/lib/module/engine/commands.js +51 -9
  419. package/lib/module/engine/commands.js.map +1 -1
  420. package/lib/module/engine/layout.js +20 -11
  421. package/lib/module/engine/layout.js.map +1 -1
  422. package/lib/module/engine/nativeScreens.js +9 -0
  423. package/lib/module/engine/nativeScreens.js.map +1 -1
  424. package/lib/module/engine/options.js +49 -15
  425. package/lib/module/engine/options.js.map +1 -1
  426. package/lib/module/engine/optionsChange.js +102 -0
  427. package/lib/module/engine/optionsChange.js.map +1 -0
  428. package/lib/module/engine/places.js +52 -7
  429. package/lib/module/engine/places.js.map +1 -1
  430. package/lib/module/engine/props.js +30 -1
  431. package/lib/module/engine/props.js.map +1 -1
  432. package/lib/module/engine/refresh.js +85 -0
  433. package/lib/module/engine/refresh.js.map +1 -0
  434. package/lib/module/engine/rememberedOptions.js +61 -1
  435. package/lib/module/engine/rememberedOptions.js.map +1 -1
  436. package/lib/module/engine/screens.js +77 -16
  437. package/lib/module/engine/screens.js.map +1 -1
  438. package/lib/module/interfaces/contract/commands.json +101 -0
  439. package/lib/module/interfaces/contract/errors.json +275 -0
  440. package/lib/typescript/adapters/NativeANNTurboModule.d.ts +12 -2
  441. package/lib/typescript/adapters/NativeANNTurboModule.d.ts.map +1 -1
  442. package/lib/typescript/api/app/AppRegistry.d.ts.map +1 -1
  443. package/lib/typescript/api/app/createNavigation.d.ts +8 -3
  444. package/lib/typescript/api/app/createNavigation.d.ts.map +1 -1
  445. package/lib/typescript/api/commands/commands.d.ts.map +1 -1
  446. package/lib/typescript/api/commands/presentation.d.ts +4 -3
  447. package/lib/typescript/api/commands/presentation.d.ts.map +1 -1
  448. package/lib/typescript/api/events/navigationEvents.d.ts +3 -3
  449. package/lib/typescript/api/events/navigationEvents.d.ts.map +1 -1
  450. package/lib/typescript/api/hooks/useNavigation.d.ts +1 -1
  451. package/lib/typescript/api/hooks/useNavigation.d.ts.map +1 -1
  452. package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts +4 -3
  453. package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts.map +1 -1
  454. package/lib/typescript/api/index.d.ts +1 -1
  455. package/lib/typescript/api/index.d.ts.map +1 -1
  456. package/lib/typescript/api/linking/dispatchedLinks.d.ts +7 -0
  457. package/lib/typescript/api/linking/dispatchedLinks.d.ts.map +1 -0
  458. package/lib/typescript/api/linking/linking.d.ts +8 -0
  459. package/lib/typescript/api/linking/linking.d.ts.map +1 -1
  460. package/lib/typescript/api/navigation.d.ts +4 -1
  461. package/lib/typescript/api/navigation.d.ts.map +1 -1
  462. package/lib/typescript/api/options/OptionsChain.d.ts +2 -2
  463. package/lib/typescript/api/screens/defineScreen.d.ts +23 -4
  464. package/lib/typescript/api/screens/defineScreen.d.ts.map +1 -1
  465. package/lib/typescript/api/screens/nativeScreens.d.ts +8 -1
  466. package/lib/typescript/api/screens/nativeScreens.d.ts.map +1 -1
  467. package/lib/typescript/api/screens/registerScreens.d.ts.map +1 -1
  468. package/lib/typescript/api/theme/theme.d.ts +2 -0
  469. package/lib/typescript/api/theme/theme.d.ts.map +1 -1
  470. package/lib/typescript/engine/commands.d.ts +5 -0
  471. package/lib/typescript/engine/commands.d.ts.map +1 -1
  472. package/lib/typescript/engine/layout.d.ts.map +1 -1
  473. package/lib/typescript/engine/nativeScreens.d.ts +5 -0
  474. package/lib/typescript/engine/nativeScreens.d.ts.map +1 -1
  475. package/lib/typescript/engine/options.d.ts +5 -2
  476. package/lib/typescript/engine/options.d.ts.map +1 -1
  477. package/lib/typescript/engine/optionsChange.d.ts +28 -0
  478. package/lib/typescript/engine/optionsChange.d.ts.map +1 -0
  479. package/lib/typescript/engine/places.d.ts +7 -2
  480. package/lib/typescript/engine/places.d.ts.map +1 -1
  481. package/lib/typescript/engine/props.d.ts +8 -1
  482. package/lib/typescript/engine/props.d.ts.map +1 -1
  483. package/lib/typescript/engine/refresh.d.ts +35 -0
  484. package/lib/typescript/engine/refresh.d.ts.map +1 -0
  485. package/lib/typescript/engine/rememberedOptions.d.ts +13 -0
  486. package/lib/typescript/engine/rememberedOptions.d.ts.map +1 -1
  487. package/lib/typescript/engine/screens.d.ts +27 -6
  488. package/lib/typescript/engine/screens.d.ts.map +1 -1
  489. package/lib/typescript/interfaces/ComponentEvents.d.ts +4 -4
  490. package/lib/typescript/interfaces/ComponentEvents.d.ts.map +1 -1
  491. package/lib/typescript/interfaces/Events.d.ts +28 -10
  492. package/lib/typescript/interfaces/Events.d.ts.map +1 -1
  493. package/lib/typescript/interfaces/Options.d.ts +1 -1
  494. package/lib/typescript/interfaces/Options.d.ts.map +1 -1
  495. package/lib/typescript/interfaces/options/animations.d.ts +80 -22
  496. package/lib/typescript/interfaces/options/animations.d.ts.map +1 -1
  497. package/lib/typescript/interfaces/options/bottomTabs.d.ts +21 -7
  498. package/lib/typescript/interfaces/options/bottomTabs.d.ts.map +1 -1
  499. package/lib/typescript/interfaces/options/buttons.d.ts +23 -15
  500. package/lib/typescript/interfaces/options/buttons.d.ts.map +1 -1
  501. package/lib/typescript/interfaces/options/modals.d.ts +34 -26
  502. package/lib/typescript/interfaces/options/modals.d.ts.map +1 -1
  503. package/lib/typescript/interfaces/options/sideMenu.d.ts +23 -6
  504. package/lib/typescript/interfaces/options/sideMenu.d.ts.map +1 -1
  505. package/lib/typescript/interfaces/options/stack.d.ts +17 -3
  506. package/lib/typescript/interfaces/options/stack.d.ts.map +1 -1
  507. package/lib/typescript/interfaces/options/system.d.ts +18 -11
  508. package/lib/typescript/interfaces/options/system.d.ts.map +1 -1
  509. package/lib/typescript/interfaces/options/toolbar.d.ts +2 -2
  510. package/lib/typescript/interfaces/options/topBar.d.ts +68 -38
  511. package/lib/typescript/interfaces/options/topBar.d.ts.map +1 -1
  512. package/metro/acceptPlugin.js +57 -0
  513. package/metro/babelTransformer.js +45 -0
  514. package/metro/index.js +36 -0
  515. package/package.json +3 -1
  516. package/src/ARCHITECTURE.md +40 -27
  517. package/src/adapters/NativeANNTurboModule.ts +12 -2
  518. package/src/api/app/AppRegistry.ts +16 -2
  519. package/src/api/app/createNavigation.ts +203 -69
  520. package/src/api/commands/commands.ts +48 -7
  521. package/src/api/commands/presentation.ts +4 -3
  522. package/src/api/events/navigationEvents.ts +10 -4
  523. package/src/api/hooks/useNavigation.ts +9 -4
  524. package/src/api/hooks/useSafeAreaInsets.ts +4 -3
  525. package/src/api/index.ts +1 -0
  526. package/src/api/linking/dispatchedLinks.ts +18 -0
  527. package/src/api/linking/linking.ts +22 -1
  528. package/src/api/navigation.ts +4 -1
  529. package/src/api/options/OptionsChain.ts +2 -2
  530. package/src/api/screens/defineScreen.ts +49 -5
  531. package/src/api/screens/nativeScreens.ts +40 -4
  532. package/src/api/screens/registerScreens.tsx +185 -42
  533. package/src/api/theme/theme.ts +5 -0
  534. package/src/engine/commands.ts +70 -13
  535. package/src/engine/layout.ts +27 -11
  536. package/src/engine/nativeScreens.ts +10 -1
  537. package/src/engine/options.ts +45 -19
  538. package/src/engine/optionsChange.ts +107 -0
  539. package/src/engine/places.ts +65 -7
  540. package/src/engine/props.ts +30 -1
  541. package/src/engine/refresh.ts +97 -0
  542. package/src/engine/rememberedOptions.ts +74 -1
  543. package/src/engine/screens.tsx +76 -21
  544. package/src/interfaces/ComponentEvents.ts +4 -4
  545. package/src/interfaces/Events.ts +29 -10
  546. package/src/interfaces/Options.ts +1 -0
  547. package/src/interfaces/contract/commands.json +101 -0
  548. package/src/interfaces/contract/errors.json +275 -0
  549. package/src/interfaces/options/animations.ts +81 -22
  550. package/src/interfaces/options/bottomTabs.ts +21 -7
  551. package/src/interfaces/options/buttons.ts +23 -15
  552. package/src/interfaces/options/modals.ts +34 -26
  553. package/src/interfaces/options/sideMenu.ts +24 -6
  554. package/src/interfaces/options/stack.ts +17 -3
  555. package/src/interfaces/options/system.ts +18 -11
  556. package/src/interfaces/options/toolbar.ts +2 -2
  557. package/src/interfaces/options/topBar.ts +68 -38
  558. package/android/src/main/java/dev/apexnative/navigation/react/ArrangementStates.kt +0 -41
  559. package/android/src/main/java/dev/apexnative/navigation/react/ScreenInsets.kt +0 -69
  560. package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationStateReporter.kt +0 -62
  561. package/android/src/main/java/dev/apexnative/navigation/react/events/StateHold.kt +0 -62
  562. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowPlacer.kt +0 -223
  563. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStub.kt +0 -31
  564. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMatrixAnimator.kt +0 -138
  565. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PlainViewAnimator.kt +0 -88
  566. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PropertyAnimatorCreator.kt +0 -33
  567. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ReactImageAnimator.kt +0 -66
  568. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextChangeAnimator.kt +0 -179
  569. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewChangeAnimator.kt +0 -139
  570. package/ios/Layouts/Screen/ANNScreenInsets.h +0 -30
  571. package/ios/Layouts/Screen/ANNScreenInsets.mm +0 -68
  572. package/ios/Layouts/Tabs/ANNTabsPreloadWindow.h +0 -27
  573. package/ios/Layouts/Tabs/ANNTabsPreloadWindow.mm +0 -55
@@ -15,6 +15,7 @@ import dev.apexnative.navigation.options.SplitViewGroupOptions
15
15
  import dev.apexnative.navigation.options.SplitViewOptions
16
16
  import dev.apexnative.navigation.react.CommandListener
17
17
  import dev.apexnative.navigation.react.CommandListenerAdapter
18
+ import dev.apexnative.navigation.react.ErrorTexts
18
19
  import dev.apexnative.navigation.react.events.EventEmitter
19
20
  import dev.apexnative.navigation.system.SystemUiOwner
20
21
  import dev.apexnative.navigation.utils.TestIds
@@ -24,13 +25,15 @@ import dev.apexnative.navigation.viewcontrollers.child.ChildControllersRegistry
24
25
  import dev.apexnative.navigation.viewcontrollers.navigator.BackCallbackState
25
26
  import dev.apexnative.navigation.viewcontrollers.navigator.Navigator
26
27
  import dev.apexnative.navigation.viewcontrollers.parent.ChildOffsetFromRest
28
+ import dev.apexnative.navigation.viewcontrollers.parent.OptionsScreen
27
29
  import dev.apexnative.navigation.viewcontrollers.parent.ParentController
28
30
  import dev.apexnative.navigation.viewcontrollers.parent.ReturnsScreenFromColumn
29
- import dev.apexnative.navigation.viewcontrollers.parent.ShowsColumns
30
31
  import dev.apexnative.navigation.viewcontrollers.parent.ShownChildren
32
+ import dev.apexnative.navigation.viewcontrollers.parent.ShowsColumns
31
33
  import dev.apexnative.navigation.viewcontrollers.stack.StackController
32
34
  import dev.apexnative.navigation.viewcontrollers.viewcontroller.Presenter
33
35
  import dev.apexnative.navigation.viewcontrollers.viewcontroller.ViewController
36
+ import kotlin.math.roundToInt
34
37
 
35
38
  /**
36
39
  * A split view: the primary pane beside the secondary one when the width takes both (a tablet, a phone in landscape).
@@ -44,8 +47,9 @@ class SplitViewController(
44
47
  presenter: Presenter,
45
48
  initialOptions: Options,
46
49
  private var split: SplitViewOptions,
47
- private val primary: ViewController<*>,
48
- private val secondary: ViewController<*>,
50
+ // The panes' content; `showInColumn` may give a pane a new one.
51
+ private var primary: ViewController<*>,
52
+ private var secondary: ViewController<*>,
49
53
  private val compact: ViewController<*>?,
50
54
  private val eventEmitter: EventEmitter,
51
55
  ) : ParentController<SplitViewLayout>(activity, childRegistry, id, presenter, initialOptions),
@@ -149,6 +153,9 @@ class SplitViewController(
149
153
 
150
154
  private fun onWidthChanged(layout: SplitViewLayout) {
151
155
  primary.getView().visibility = if (primaryHidden && layout.isWide == true) View.GONE else View.VISIBLE
156
+ // Compact, side by side or one over the other decides what back does from this measure on: the callback only
157
+ // takes its value here, nothing moves; the panes' end below computes it again.
158
+ BackCallbackState.update()
152
159
  // Where a later `compactTopColumn` puts the pane over the other at this switch: true open, false closed.
153
160
  val settle = if (measured && isSliding) laterTopColumn?.let { it == SECONDARY } else null
154
161
  if (!measured) {
@@ -365,6 +372,19 @@ class SplitViewController(
365
372
  return can || super.canHandleBack()
366
373
  }
367
374
 
375
+ // As handleBack: the pane whose back goes first decides; an open sliding pane that would close previews nothing.
376
+ override fun stackPoppedByBack(): StackController? {
377
+ if (!isViewCreated) return super.stackPoppedByBack()
378
+ val layout = getView()
379
+ return when {
380
+ layout.isCompact -> compact?.stackPoppedByBack()
381
+ isSliding && !layout.panes.isOpen -> primary.stackPoppedByBack()
382
+ isSliding -> if (secondary.canHandleBack()) secondary.stackPoppedByBack() else null
383
+ secondary.canHandleBack() -> secondary.stackPoppedByBack()
384
+ else -> primary.stackPoppedByBack()
385
+ }
386
+ }
387
+
368
388
  /**
369
389
  * How far the pane of [child] is from where it rests: the secondary pane sliding over the primary one rests over
370
390
  * it, closed or on its way. Zero for the other children.
@@ -407,27 +427,67 @@ class SplitViewController(
407
427
  }
408
428
 
409
429
  /**
410
- * Shows [screen] in the secondary pane in place of what it shows and brings the pane into view. False with the
411
- * compact layout on screen: the screen goes over [from], the screen the command comes from.
430
+ * Shows [screen] in [column] (`primary` or `secondary`; Android has no other) in place of what the pane shows, and
431
+ * brings the pane into view. A stack pane's screens are replaced by it, unless it is a container
432
+ * (![goesInStack]): `columnIsStack`. Any other pane is taken by it, and its content goes. A column the split view
433
+ * doesn't have: `noSuchColumn`. False with the compact layout on screen: the screen goes over [from], the screen
434
+ * the command comes from.
412
435
  */
413
- override fun showScreen(screen: ViewController<*>, from: ViewController<*>, listener: CommandListener): Boolean {
436
+ override fun showScreen(
437
+ screen: ViewController<*>,
438
+ column: String,
439
+ goesInStack: Boolean,
440
+ from: ViewController<*>,
441
+ listener: CommandListener,
442
+ ): Boolean {
414
443
  if (isViewCreated && getView().isCompact) return false
415
- val stack = secondary as? StackController
416
- if (stack == null) {
417
- listener.onError("the 'secondary' column of the split view of the screen '${from.id}' is not a stack")
418
- return true
444
+ val pane = when (column) {
445
+ PRIMARY -> primary
446
+ SECONDARY -> secondary
447
+ else -> null
419
448
  }
420
- stack.setRoot(listOf(screen), false, object : CommandListenerAdapter() {
421
- override fun onSuccess(childId: String) {
449
+ when {
450
+ pane == null -> listener.onError(ErrorTexts.noSuchColumn(from.id, column))
451
+ pane is StackController && !goesInStack -> listener.onError(ErrorTexts.columnIsStack(from.id, column))
452
+ pane is StackController -> pane.setRoot(listOf(screen), false, object : CommandListenerAdapter() {
453
+ override fun onSuccess(childId: String) {
454
+ updateBackButton()
455
+ bringIntoView(column) { listener.onSuccess(childId) }
456
+ }
457
+
458
+ override fun onError(message: String) = listener.onError(message)
459
+ })
460
+ else -> {
461
+ replacePane(pane, screen)
422
462
  updateBackButton()
423
- showSecondary { listener.onSuccess(childId) }
463
+ val shownId = ((screen as? OptionsScreen)?.optionsScreen ?: screen).id
464
+ bringIntoView(column) { listener.onSuccess(shownId) }
424
465
  }
425
-
426
- override fun onError(message: String) = listener.onError(message)
427
- })
466
+ }
428
467
  return true
429
468
  }
430
469
 
470
+ // [next] takes the pane of [old], a screen alone or a container, as iOS puts a screen in place of a column's: its
471
+ // view goes where the old one's was, the children shown are told as a move of the panes tells them (DidDisappear
472
+ // of what left, DidAppear of what came), and [old] goes with its screens.
473
+ private fun replacePane(old: ViewController<*>, next: ViewController<*>) {
474
+ next.setParentController(this)
475
+ if (old === primary) primary = next else secondary = next
476
+ peekView()?.let { layout ->
477
+ layout.panes.replacePane(old.getView(), next.getView())
478
+ applyTestIds(primary.getView(), secondary.getView())
479
+ hideCoveredPane()
480
+ shownChildren.moved()
481
+ tellShownChanged()
482
+ }
483
+ old.destroy()
484
+ }
485
+
486
+ // The pane of [column] comes into view; [done] once the panes stopped.
487
+ private fun bringIntoView(column: String, done: Runnable) {
488
+ if (column == PRIMARY) setColumnShown(PRIMARY, true, done) else showSecondary(done)
489
+ }
490
+
431
491
  private fun showSecondary(done: Runnable) {
432
492
  if (!isSliding || getView().panes.isOpen) {
433
493
  done.run()
@@ -489,7 +549,7 @@ class SplitViewController(
489
549
  root.mergeOptions(options)
490
550
  }
491
551
 
492
- private fun dp(value: Double) = UiUtils.dpToPx(activity, value.toFloat()).toInt()
552
+ private fun dp(value: Double) = UiUtils.dpToPx(activity, value.toFloat()).roundToInt()
493
553
 
494
554
  companion object {
495
555
  private const val PRIMARY = "primary"
@@ -0,0 +1,315 @@
1
+ package dev.apexnative.navigation.viewcontrollers.stack
2
+
3
+ import android.animation.Animator
4
+ import android.animation.AnimatorListenerAdapter
5
+ import android.animation.StateListAnimator
6
+ import android.animation.ValueAnimator
7
+ import android.content.res.Configuration
8
+ import android.graphics.Bitmap
9
+ import android.graphics.Canvas
10
+ import android.graphics.Color
11
+ import android.graphics.Outline
12
+ import android.graphics.Rect
13
+ import android.os.Build
14
+ import android.os.Handler
15
+ import android.os.Looper
16
+ import android.view.PixelCopy
17
+ import android.view.View
18
+ import android.view.ViewGroup
19
+ import android.view.ViewOutlineProvider
20
+ import android.view.Window
21
+ import android.view.animation.DecelerateInterpolator
22
+ import android.view.animation.LinearInterpolator
23
+ import android.view.animation.PathInterpolator
24
+ import android.widget.ImageView
25
+ import androidx.coordinatorlayout.widget.CoordinatorLayout
26
+ import dev.apexnative.navigation.views.animations.SystemTransition
27
+ import dev.apexnative.navigation.views.stack.StackLayout
28
+
29
+ /**
30
+ * The preview of a pop while the user's back gesture runs (predictive back), as the system shows the activity under
31
+ * the one that closes: the screen on top with its bar, a picture taken as the gesture starts, shrinks toward the
32
+ * gesture's side with rounded corners and follows the finger up and down; the screen under it shows behind it with
33
+ * its own bar and FAB, smaller and dimmed. Released, the pop plays its end ([commit]); cancelled, everything goes back
34
+ * ([cancel]). The values are those of the system's cross-activity back animation (WMShell
35
+ * `DefaultCrossActivityBackAnimation` of Android 15 and 16, the smallest scale as Android 17 shows it), also on Android
36
+ * 14, whose own preview differs. Main thread only.
37
+ */
38
+ internal class BackPreview(
39
+ private val layout: StackLayout,
40
+ private val top: View,
41
+ private val target: View,
42
+ /** The gesture started at the left edge: the screen moves right; from the right edge it stays centered. */
43
+ private val fromLeft: Boolean,
44
+ private val startY: Float,
45
+ /**
46
+ * The room the tabs take at the bottom of the top screen: the card is the stack above them, rounded on all four
47
+ * corners, while the tab bar stays, as Gmail shows it.
48
+ */
49
+ private val bottomRoom: Int,
50
+ /**
51
+ * The picture is there: the stack shows the screen under the top, with its bar and its FAB, before the preview
52
+ * draws.
53
+ */
54
+ private val onReveal: () -> Unit,
55
+ /** The view of the FAB the stack shows now, which goes with the screen under the top; none. */
56
+ private val fab: () -> View? = { null },
57
+ ) {
58
+ private val density = layout.resources.displayMetrics.density
59
+ private val bar = layout.topBar
60
+ private val scrim = View(layout.context)
61
+ private var card: ImageView? = null
62
+ private var progress = 0f
63
+ private var touchY = startY
64
+ private var animator: Animator? = null
65
+ private var ended = false
66
+ private var topAlpha = 1f
67
+ // The FAB that shows with the screen under the top, drawn flat under the dim and the picture, its own Z and the
68
+ // animator of its Z by its state.
69
+ private var flatFab: View? = null
70
+ private var fabZ = 0f
71
+ private var fabZByState: StateListAnimator? = null
72
+ // What puts the stack as it was after a cancel: once, as the preview ends.
73
+ private var onCancelled: (() -> Unit)? = null
74
+ // Forward is to the end of the line: right to left, the screens move the other way, as the stack's pop does.
75
+ private val forward = if (layout.layoutDirection == View.LAYOUT_DIRECTION_RTL) -1f else 1f
76
+
77
+ /** The picture of the top is there and the screen under it shows: the preview draws. */
78
+ val isReady: Boolean
79
+ get() = card != null && !ended
80
+
81
+ /**
82
+ * Takes the picture of the stack as it shows now, drawn from its views (what lies over the stack, an overlay or a
83
+ * tab bar drawn over it, stays out of it); with a hardware bitmap in it, copied from the window a frame later. The
84
+ * preview draws once it is there.
85
+ */
86
+ fun start(window: Window) {
87
+ val width = layout.width
88
+ val height = areaHeight
89
+ if (width <= 0 || height <= 0) return
90
+ val picture = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
91
+ try {
92
+ layout.draw(Canvas(picture))
93
+ show(picture)
94
+ return
95
+ } catch (e: IllegalArgumentException) {
96
+ picture.eraseColor(Color.TRANSPARENT)
97
+ }
98
+ val place = IntArray(2)
99
+ layout.getLocationInWindow(place)
100
+ val area = Rect(place[0], place[1], place[0] + width, place[1] + height)
101
+ PixelCopy.request(window, area, picture, { result ->
102
+ if (result == PixelCopy.SUCCESS && !ended) show(picture)
103
+ }, Handler(Looper.getMainLooper()))
104
+ }
105
+
106
+ /** The gesture moved: [value] is its progress, 0 … 1, and [y] the finger's height in the window. */
107
+ fun progress(value: Float, y: Float) {
108
+ progress = value
109
+ touchY = y
110
+ if (isReady) drawGesture(GESTURE_CURVE.getInterpolation(value))
111
+ }
112
+
113
+ /**
114
+ * The gesture was cancelled: the preview springs back, then [restore] puts the stack as it was; at once when the
115
+ * preview ends earlier (a new gesture, a command).
116
+ */
117
+ fun cancel(restore: () -> Unit) {
118
+ onCancelled = restore
119
+ if (!isReady) return endAtOnce()
120
+ val from = progress
121
+ animator?.cancel()
122
+ animator = ValueAnimator.ofFloat(from, 0f).apply {
123
+ duration = CANCEL_MILLIS
124
+ interpolator = DecelerateInterpolator()
125
+ addUpdateListener { drawGesture(GESTURE_CURVE.getInterpolation(it.animatedValue as Float)) }
126
+ addListener(object : AnimatorListenerAdapter() {
127
+ override fun onAnimationEnd(animation: Animator) {
128
+ if (animator === animation) endAtOnce()
129
+ }
130
+ })
131
+ start()
132
+ }
133
+ }
134
+
135
+ /**
136
+ * The gesture was released and the pop runs: the top goes back to its size while it moves away by 96 dp and fades
137
+ * in the first fifth, the screen under it grows to its place, the dim fades; [done] once at the end, after the
138
+ * preview took its views away.
139
+ */
140
+ fun commit(done: () -> Unit) {
141
+ val card = card ?: return done()
142
+ val distance = SystemTransition.DISTANCE_DP * density
143
+ val q = GESTURE_CURVE.getInterpolation(progress)
144
+ val scale = scaleAt(q)
145
+ val cardX = card.translationX
146
+ val cardY = card.translationY
147
+ val dim = scrim.alpha
148
+ animator?.cancel()
149
+ animator = ValueAnimator.ofFloat(0f, 1f).apply {
150
+ duration = SystemTransition.DURATION
151
+ interpolator = LinearInterpolator()
152
+ addUpdateListener {
153
+ val t = it.animatedValue as Float
154
+ val e = SystemTransition.CURVE.getInterpolation(t)
155
+ card.scaleX = lerp(scale, 1f, e)
156
+ card.scaleY = card.scaleX
157
+ card.translationX = lerp(cardX, distance * forward, e)
158
+ card.translationY = lerp(cardY, 0f, e)
159
+ card.alpha = (1f - 5f * t).coerceAtLeast(0f)
160
+ entering(lerp(scale, 1f, e), lerp(-distance * forward, 0f, e))
161
+ scrim.alpha = lerp(dim, 0f, t)
162
+ }
163
+ addListener(object : AnimatorListenerAdapter() {
164
+ override fun onAnimationEnd(animation: Animator) {
165
+ if (animator !== animation) return
166
+ endAtOnce()
167
+ done()
168
+ }
169
+ })
170
+ start()
171
+ }
172
+ }
173
+
174
+ /**
175
+ * The preview ends where it is: its views go, the screens and the bar take their own values again, and a cancel's
176
+ * restore runs.
177
+ */
178
+ fun endAtOnce() {
179
+ if (ended) return
180
+ ended = true
181
+ animator?.let {
182
+ animator = null
183
+ it.cancel()
184
+ }
185
+ card?.let { (it.parent as? ViewGroup)?.removeView(it) }
186
+ card = null
187
+ (scrim.parent as? ViewGroup)?.removeView(scrim)
188
+ top.alpha = topAlpha
189
+ flatFab?.let {
190
+ flatFab = null
191
+ it.translationZ = fabZ
192
+ it.stateListAnimator = fabZByState
193
+ fabZByState = null
194
+ }
195
+ entering(1f, 0f)
196
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
197
+ target.resetPivot()
198
+ bar.resetPivot()
199
+ fab()?.resetPivot()
200
+ }
201
+ onCancelled?.let {
202
+ onCancelled = null
203
+ it()
204
+ }
205
+ }
206
+
207
+ // The picture came: the screen under the top shows with its bar, dimmed, and the picture lies over everything in
208
+ // the top's place, cut to rounded corners.
209
+ private fun show(picture: Bitmap) {
210
+ onReveal()
211
+ // A child with a Z draws over those without, whatever their order: the FAB, raised by its elevation, would lie
212
+ // over the dim and the picture. Its state's animator, which Material's FAB sets on the frame after it joins the
213
+ // window (and on a press, focus or hover), would raise it again: it stays off while the preview draws.
214
+ fab()?.takeIf { it.z > 0f }?.let {
215
+ flatFab = it
216
+ fabZ = it.translationZ
217
+ fabZByState = it.stateListAnimator
218
+ it.stateListAnimator = null
219
+ it.translationZ = -it.elevation
220
+ }
221
+ val dark = layout.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK ==
222
+ Configuration.UI_MODE_NIGHT_YES
223
+ scrim.setBackgroundColor(Color.BLACK)
224
+ scrim.alpha = if (dark) SCRIM_DARK else SCRIM_LIGHT
225
+ scrim.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
226
+ layout.addOverAll(scrim, fill())
227
+ val radius = CORNER_DP * density
228
+ val area = CoordinatorLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, areaHeight)
229
+ card = ImageView(layout.context).apply {
230
+ setImageBitmap(picture)
231
+ scaleType = ImageView.ScaleType.FIT_XY
232
+ importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO
233
+ outlineProvider = object : ViewOutlineProvider() {
234
+ override fun getOutline(view: View, outline: Outline) =
235
+ outline.setRoundRect(0, 0, view.width, view.height, radius)
236
+ }
237
+ clipToOutline = true
238
+ layout.addOverAll(this, area)
239
+ }
240
+ // Transparent, not invisible: a surface in it (a video, a map) stays, and so does the focus.
241
+ topAlpha = top.alpha
242
+ top.alpha = 0f
243
+ drawGesture(GESTURE_CURVE.getInterpolation(progress))
244
+ }
245
+
246
+ // The values of the gesture at [q], its progress on the system's curve.
247
+ private fun drawGesture(q: Float) {
248
+ val card = card ?: return
249
+ val width = layout.width.toFloat()
250
+ val height = areaHeight.toFloat()
251
+ val margin = MARGIN_DP * density
252
+ val scale = scaleAt(q)
253
+ card.scaleX = scale
254
+ card.scaleY = scale
255
+ // From the left edge the screen's right side ends 8 dp from the window's right edge; from the right edge it stays
256
+ // centered.
257
+ card.translationX = if (fromLeft) (width - width * scale) / 2f - margin * q else 0f
258
+ // Up and down with the finger, never closer than 8 dp to the window's edges.
259
+ val moved = touchY - startY
260
+ val ratio = FOLLOW_CURVE.getInterpolation((kotlin.math.abs(moved) / (height / 2f)).coerceAtMost(1f))
261
+ card.translationY = ((height - height * scale) / 2f - margin).coerceAtLeast(0f) * ratio *
262
+ Math.signum(moved)
263
+ entering(scale, -SystemTransition.DISTANCE_DP * density * forward)
264
+ }
265
+
266
+ // The screen under the top, its bar and its FAB at [scale] around the stack's center, [x] along the line.
267
+ private fun entering(scale: Float, x: Float) {
268
+ for (view in listOfNotNull(target, bar, fab())) {
269
+ view.pivotX = layout.width / 2f - view.left
270
+ view.pivotY = areaHeight / 2f - view.top
271
+ view.scaleX = scale
272
+ view.scaleY = scale
273
+ view.translationX = x
274
+ }
275
+ }
276
+
277
+ // The stack above the tabs' room: what the card shows and what the screens shrink around.
278
+ private val areaHeight: Int
279
+ get() = (layout.height - bottomRoom).coerceAtLeast(0)
280
+
281
+ private fun scaleAt(q: Float): Float = 1f - (1f - minScale()) * q
282
+
283
+ private fun fill() = CoordinatorLayout.LayoutParams(
284
+ ViewGroup.LayoutParams.MATCH_PARENT,
285
+ ViewGroup.LayoutParams.MATCH_PARENT,
286
+ )
287
+
288
+ private fun lerp(from: Float, to: Float, fraction: Float): Float = from + (to - from) * fraction
289
+
290
+ private companion object {
291
+ /** The system's curve of the back gesture's progress (`BackGestureInterpolator`). */
292
+ val GESTURE_CURVE = PathInterpolator(0.1f, 0.1f, 0f, 1f)
293
+
294
+ /** How the screen follows the finger up and down. */
295
+ val FOLLOW_CURVE = DecelerateInterpolator()
296
+
297
+ /** The room the shrunk screen keeps from the window's edges. */
298
+ const val MARGIN_DP = 8f
299
+
300
+ /** The corners of the shrunk screen, as Android 17 draws them on a Pixel (6.5 dp at its smallest). */
301
+ const val CORNER_DP = 7.5f
302
+
303
+ const val SCRIM_LIGHT = 0.2f
304
+ const val SCRIM_DARK = 0.8f
305
+
306
+ /** The cancel springs back about as fast as the system's (`BackProgressAnimator`'s spring, no bounce). */
307
+ const val CANCEL_MILLIS = 350L
308
+
309
+ /**
310
+ * The smallest scale of the screens: 0.9 in WMShell of Android 15 and 16 (and here on Android 14); Android 17
311
+ * shrinks the window further (0.86, measured on a Pixel 6).
312
+ */
313
+ fun minScale(): Float = if (android.os.Build.VERSION.SDK_INT >= 37) 0.86f else 0.9f
314
+ }
315
+ }
@@ -2,18 +2,18 @@ package dev.apexnative.navigation.viewcontrollers.stack
2
2
 
3
3
  import android.view.View
4
4
  import com.facebook.react.uimanager.PixelUtil.pxToDp
5
- import dev.apexnative.navigation.react.ScreenInsets
5
+ import dev.apexnative.navigation.react.ScreenEnvironment
6
6
 
7
7
  /**
8
8
  * Where a screen prepared for a push (`preparePush`) shows, in dp: the size of the container its slot fills and the
9
9
  * padding of its safe area view, as the push lays it out. JavaScript renders the screen with them before the push, and
10
10
  * the slot and the safe area view start their states with them.
11
11
  */
12
- internal data class PreparedFrame(val width: Float, val height: Float, val padding: ScreenInsets.Insets) {
12
+ internal data class PreparedFrame(val width: Float, val height: Float, val padding: ScreenEnvironment.Insets) {
13
13
  companion object {
14
14
  /** The size of [container] as its slot measures it (`SlotView`), so the slot finds it equal. */
15
15
  @JvmStatic
16
- fun of(container: View, padding: ScreenInsets.Insets) =
16
+ fun of(container: View, padding: ScreenEnvironment.Insets) =
17
17
  PreparedFrame(container.width.toFloat().pxToDp(), container.height.toFloat().pxToDp(), padding)
18
18
  }
19
19
  }
@@ -11,7 +11,7 @@ import dev.apexnative.navigation.options.DefaultOptions
11
11
  import dev.apexnative.navigation.react.CommandAnswer
12
12
  import dev.apexnative.navigation.react.CommandListener
13
13
  import dev.apexnative.navigation.react.ErrorTexts
14
- import dev.apexnative.navigation.react.ScreenInsets
14
+ import dev.apexnative.navigation.react.ScreenEnvironment
15
15
  import dev.apexnative.navigation.slots.SlotScreenView
16
16
  import dev.apexnative.navigation.utils.NavigationLog
17
17
  import dev.apexnative.navigation.viewcontrollers.child.ChildControllersRegistry
@@ -105,33 +105,42 @@ internal class StackCommands(
105
105
  }
106
106
 
107
107
  /**
108
- * `showInColumn` (Android): [layout] in the secondary pane of the split view of the screen [componentId], or over
109
- * that screen in its stack. Before any node: the screen is there, else `the screen '<id>' is not shown`; the push's
110
- * checks of the layout (an id that shows already; a container, which the stack of the screen, else its split view,
111
- * doesn't take); a screen prepared with the id goes. The screen is made at once, a native screen's view too. The
112
- * split view takes it (the answer once its pane stopped, or the rejection of the pane); with the compact layout on
113
- * screen, or without a split view, it is pushed over [componentId] in its stack, with the push's answer and errors;
114
- * neither: `the screen '<id>' is neither in a split view nor in a stack`. Every rejection after the screen was made
115
- * destroys it. Two calls in a row each make their screen the root of the pane in turn, and each answers its own id.
108
+ * `showInColumn` (Android): [layout] in [column] of the split view of the screen [componentId], or over that screen
109
+ * in its stack. Before any node: the screen is there, else `the screen '<id>' is not shown`; the layout has no id
110
+ * that shows already; out of a split view, the push's check of the layout (a container, which the stack doesn't
111
+ * take); a screen prepared with the id goes. The screen is made at once, a native screen's view too. The split view
112
+ * takes it — in place of a stack column's screens or of a column's content — with the answer once its pane
113
+ * stopped, or rejects (a column it doesn't have, a container for a stack column); with the compact layout on
114
+ * screen, or without a split view, it is pushed over [componentId] in its stack, with the push's checks, answer and
115
+ * errors; neither: `the screen '<id>' is neither in a split view nor in a stack`. Every rejection after the screen
116
+ * was made destroys it. Two calls in a row each make their screen the column's content in turn, and each answers
117
+ * its own id.
116
118
  */
117
- fun showInColumn(componentId: String, layout: LayoutNode, answer: CommandAnswer, what: String) {
119
+ fun showInColumn(componentId: String, column: String, layout: LayoutNode, answer: CommandAnswer, what: String) {
118
120
  val source = find(componentId)?.takeIf { !prepared.isPrepared(it) }
119
121
  ?: return answer.reject(ErrorTexts.screenNotShown(componentId))
120
122
  val shown = LayoutChecks.firstShownId(listOf(layout), ::isShown) { false }
121
123
  if (shown != null) return answer.reject(ErrorTexts.alreadyShown(shown))
122
124
  val columns = nodeWith<ShowsColumns>(source)
123
125
  val stack = source as? StackController ?: source.findParentStack()
124
- val placeId = stack?.id ?: (columns as? ViewController<*>)?.id
125
- placeId?.let { id -> LayoutChecks.checkStackChild(layout, id)?.let { return answer.reject(it) } }
126
+ // Out of a split view it can only be a push: the stack's check comes before any node.
127
+ if (columns == null && stack != null) {
128
+ LayoutChecks.checkStackChild(layout, stack.id)?.let { return answer.reject(it) }
129
+ }
126
130
  if (!factory.canMake(layout)) return answer.reject(ErrorTexts.notDoneYet("showInColumn"))
127
131
  prepared.discard(layout.id)
128
132
  val node = make(layout)
129
133
  try {
130
- if (columns?.showScreen(node, source, destroyingOnError(node, answer)) == true) return
134
+ val goesInStack = LayoutChecks.isStackChild(layout)
135
+ if (columns?.showScreen(node, column, goesInStack, source, destroyingOnError(node, answer)) == true) return
131
136
  if (stack == null) {
132
137
  node.destroy()
133
138
  return answer.reject(ErrorTexts.neitherSplitViewNorStack(componentId))
134
139
  }
140
+ LayoutChecks.checkStackChild(layout, stack.id)?.let {
141
+ node.destroy()
142
+ return answer.reject(it)
143
+ }
135
144
  pushMade(stack, source, node, layout, answer, what)
136
145
  } catch (e: Throwable) {
137
146
  node.destroy()
@@ -225,8 +234,9 @@ internal class StackCommands(
225
234
  fun setStackRoot(componentId: String, layouts: List<LayoutNode>, answer: CommandAnswer, what: String) {
226
235
  if (layouts.isEmpty()) return answer.reject(ErrorTexts.noScreensForStack(componentId))
227
236
  val stack = stackOf(componentId, answer) ?: return
228
- // An id of this stack may come again: the new screen replaces it (`setStackRoot` step 3).
229
- val shown = LayoutChecks.firstShownId(layouts, { isShown(it) && !isOf(stack, it) }) { false }
237
+ // An id of an entry of this stack may come again: the new screen replaces it (`setStackRoot` step 3). The
238
+ // stack's own id, and a screen an accepted cut or replace took away, show elsewhere or still go: as on iOS.
239
+ val shown = LayoutChecks.firstShownId(layouts, ::isShown) { isInEntryOf(stack, it.id) }
230
240
  if (shown != null) return answer.reject(ErrorTexts.alreadyShown(shown))
231
241
  for (layout in layouts) LayoutChecks.checkStackChild(layout, stack.id)?.let { return answer.reject(it) }
232
242
  if (!layouts.all(factory::canMake)) return answer.reject(ErrorTexts.notDoneYet("setStackRoot"))
@@ -308,7 +318,7 @@ internal class StackCommands(
308
318
  layoutNow(stackView, screenView)
309
319
  node.updateSafeArea()
310
320
  val content = node.content?.asView()
311
- val padding = ScreenInsets.padding(node.id)
321
+ val padding = ScreenEnvironment.padding(node.id)
312
322
  val noInsets = content == null || ViewCompat.getRootWindowInsets(content) == null
313
323
  if (noInsets || padding == null || content.width <= 0 || content.height <= 0) {
314
324
  prepared.discard(node.id)
@@ -357,10 +367,10 @@ internal class StackCommands(
357
367
  // A node of the registry has [id], and it isn't only prepared for a push (`push` step 1, `preparePush`).
358
368
  private fun isShown(id: String): Boolean = registry.find(id)?.let { !prepared.isPrepared(it) } == true
359
369
 
360
- // The node with [id] is [stack] or in it.
361
- private fun isOf(stack: StackController, id: String): Boolean {
362
- val node = find(id) ?: return false
363
- return node === stack || node.findParentStack() === stack
370
+ // The node with [id] is in an entry of [stack] as JavaScript sees it (`StackQueue.entries`), not the stack itself.
371
+ private fun isInEntryOf(stack: StackController, id: String): Boolean {
372
+ val node = find(id)?.takeIf { it !== stack } ?: return false
373
+ return stack.entryOf(node)?.let { it in stack.queue.entries } == true
364
374
  }
365
375
 
366
376
  // A node of [layout], with its view made now when it has a native screen: its creator's failure rejects the