@apexnative/navigation 1.0.0-alpha.5 → 1.0.0-alpha.7

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 (358) hide show
  1. package/ApexNavigation.podspec +2 -1
  2. package/CHANGELOG.md +32 -0
  3. package/README.md +1 -1
  4. package/android/CLAUDE.md +31 -20
  5. package/android/CORE.md +12 -8
  6. package/android/consumer-rules.pro +6 -0
  7. package/android/src/main/java/dev/apexnative/navigation/NavigationActivity.kt +36 -5
  8. package/android/src/main/java/dev/apexnative/navigation/options/BottomTabOptions.kt +1 -1
  9. package/android/src/main/java/dev/apexnative/navigation/options/BottomTabsOptions.kt +13 -8
  10. package/android/src/main/java/dev/apexnative/navigation/options/ButtonOptions.kt +1 -1
  11. package/android/src/main/java/dev/apexnative/navigation/options/LargeTitleOptions.kt +1 -1
  12. package/android/src/main/java/dev/apexnative/navigation/options/LayoutAnimation.kt +1 -1
  13. package/android/src/main/java/dev/apexnative/navigation/options/OptionKey.kt +18 -0
  14. package/android/src/main/java/dev/apexnative/navigation/options/OptionPaths.kt +91 -0
  15. package/android/src/main/java/dev/apexnative/navigation/options/SheetOptions.kt +7 -4
  16. package/android/src/main/java/dev/apexnative/navigation/options/TitleOptions.kt +2 -2
  17. package/android/src/main/java/dev/apexnative/navigation/options/TopBarAppearanceOptions.kt +1 -1
  18. package/android/src/main/java/dev/apexnative/navigation/options/TopBarOptions.kt +16 -7
  19. package/android/src/main/java/dev/apexnative/navigation/react/ContentHeights.kt +95 -0
  20. package/android/src/main/java/dev/apexnative/navigation/react/ContentMounts.kt +66 -0
  21. package/android/src/main/java/dev/apexnative/navigation/react/NavigationTurboModule.kt +7 -3
  22. package/android/src/main/java/dev/apexnative/navigation/react/OptionsCommands.kt +41 -3
  23. package/android/src/main/java/dev/apexnative/navigation/react/ReactView.kt +16 -1
  24. package/android/src/main/java/dev/apexnative/navigation/react/ReloadCoordinator.kt +0 -2
  25. package/android/src/main/java/dev/apexnative/navigation/react/ScreenEnvironment.kt +177 -0
  26. package/android/src/main/java/dev/apexnative/navigation/react/ScreenRegions.kt +12 -49
  27. package/android/src/main/java/dev/apexnative/navigation/react/ScrollEvents.kt +49 -128
  28. package/android/src/main/java/dev/apexnative/navigation/safearea/SafeAreaView.kt +6 -6
  29. package/android/src/main/java/dev/apexnative/navigation/slots/SlotScreenView.kt +27 -7
  30. package/android/src/main/java/dev/apexnative/navigation/slots/SlotView.kt +12 -1
  31. package/android/src/main/java/dev/apexnative/navigation/utils/MaterialTheme.kt +5 -6
  32. package/android/src/main/java/dev/apexnative/navigation/utils/SystemAnimations.kt +36 -0
  33. package/android/src/main/java/dev/apexnative/navigation/utils/ViewExtensions.kt +0 -13
  34. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementController.kt +9 -7
  35. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsCollapseBehavior.kt +5 -3
  36. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsController.kt +13 -10
  37. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowGeometry.kt +22 -0
  38. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabsRoom.kt +0 -5
  39. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentViewController.kt +7 -8
  40. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenSafeArea.kt +29 -11
  41. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/externalcomponent/ExternalComponentViewController.kt +2 -6
  42. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalCoordinator.kt +20 -2
  43. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalSheet.kt +443 -58
  44. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalViews.kt +33 -5
  45. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetBack.kt +42 -0
  46. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetStops.kt +60 -2
  47. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/Navigator.kt +4 -0
  48. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ParentController.kt +3 -6
  49. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuMotion.kt +8 -2
  50. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/BackPreview.kt +32 -4
  51. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/PreparedFrame.kt +3 -3
  52. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackCommands.kt +2 -2
  53. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackController.kt +50 -7
  54. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackQueue.kt +15 -3
  55. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackViews.kt +10 -4
  56. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabMotion.kt +142 -0
  57. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabPresenter.kt +215 -43
  58. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/StackSearchPresenter.kt +25 -26
  59. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarRowTransition.kt +3 -2
  60. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/ButtonPlaces.kt +11 -5
  61. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarPresenter.kt +36 -38
  62. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ScrollEventListener.kt +6 -9
  63. package/android/src/main/java/dev/apexnative/navigation/views/animations/AnimationLayer.kt +73 -0
  64. package/android/src/main/java/dev/apexnative/navigation/views/animations/ValueInterpolation.kt +14 -0
  65. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabsLayout.kt +61 -2
  66. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomTabRow.kt +72 -10
  67. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementTransitions.kt +129 -179
  68. package/android/src/main/java/dev/apexnative/navigation/views/element/TargetsWait.kt +8 -1
  69. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionLayer.kt +37 -112
  70. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ElementPictures.kt +67 -3
  71. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/FlightGeometry.kt +346 -36
  72. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMorph.kt +199 -0
  73. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/SharedAnimatorFactory.kt +55 -42
  74. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextMorph.kt +176 -0
  75. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewMorph.kt +108 -0
  76. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabCopy.kt +85 -0
  77. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabMenu.kt +13 -0
  78. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TitleBar.kt +5 -24
  79. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TopBar.kt +51 -34
  80. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonComponentCell.kt +6 -6
  81. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonView.kt +113 -0
  82. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarMenu.kt +219 -0
  83. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonBar.kt +121 -175
  84. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonMenus.kt +34 -64
  85. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonRow.kt +216 -0
  86. package/android/src/main/jni/ANNContentHeights.cpp +82 -0
  87. package/android/src/main/res/drawable/apex_navigation_ic_arrow_right.xml +14 -0
  88. package/android/src/main/res/layout/apex_navigation_menu_header.xml +19 -0
  89. package/android/src/main/res/layout/apex_navigation_menu_item.xml +68 -0
  90. package/android/src/main/res/values/styles.xml +1 -1
  91. package/android/src/main/res/values-night/styles.xml +1 -1
  92. package/cli/doctor/checks/app.js +16 -1
  93. package/cli/project.js +4 -0
  94. package/cli/setup/index.js +5 -0
  95. package/cli/setup/steps/metro.js +46 -0
  96. package/docs-md/architecture/native-screens.md +4 -0
  97. package/docs-md/architecture/theme-and-context.md +131 -12
  98. package/docs-md/architecture/transitions.md +46 -5
  99. package/docs-md/containers/modals.md +2 -0
  100. package/docs-md/containers/overlays.md +1 -1
  101. package/docs-md/containers/side-menu.md +1 -1
  102. package/docs-md/containers/tabs.md +2 -0
  103. package/docs-md/flows/bottom-sheets.md +4 -2
  104. package/docs-md/fundamentals/screens-and-props.md +9 -1
  105. package/docs-md/fundamentals/starting-the-app.md +1 -1
  106. package/docs-md/guides/cli.md +3 -1
  107. package/docs-md/help/glossary.md +2 -2
  108. package/docs-md/help/troubleshooting.md +22 -1
  109. package/docs-md/index.json +41 -1
  110. package/docs-md/migration/from-expo-router.md +1 -1
  111. package/docs-md/migration/from-react-native-navigation.md +1 -1
  112. package/docs-md/migration/from-react-navigation.md +2 -2
  113. package/docs-md/screen-ui/back-and-gestures.md +17 -1
  114. package/docs-md/screen-ui/bar-buttons.md +5 -5
  115. package/docs-md/screen-ui/search.md +1 -1
  116. package/docs-md/screen-ui/system-ui.md +16 -11
  117. package/docs-md/screen-ui/toolbar-and-fab.md +4 -2
  118. package/docs-md/screen-ui/top-bar.md +8 -4
  119. package/docs-md/start/installation.md +16 -1
  120. package/ios/Animations/ANNFrameDriver.h +55 -15
  121. package/ios/Animations/ANNFrameDriver.mm +216 -60
  122. package/ios/Animations/ANNTransitionAnimator.h +26 -5
  123. package/ios/Animations/ANNTransitionAnimator.mm +49 -3
  124. package/ios/Animations/ANNTransitionPlan.h +2 -2
  125. package/ios/Animations/ANNTransitionPlan.mm +10 -0
  126. package/ios/Animations/Elements/ANNElementFinder.h +2 -2
  127. package/ios/Animations/Elements/ANNElementFinder.mm +2 -2
  128. package/ios/Animations/Elements/ANNElementTransition.h +3 -3
  129. package/ios/Animations/Elements/ANNElementTransition.mm +2 -2
  130. package/ios/Animations/Elements/ANNSharedElementFlight.h +3 -3
  131. package/ios/Animations/Elements/ANNSharedElementFlight.mm +249 -45
  132. package/ios/Animations/Interpolators/ANNInterpolate.h +2 -30
  133. package/ios/Animations/Interpolators/ANNTransformParts.h +48 -0
  134. package/ios/Animations/Interpolators/ANNTransformParts.mm +507 -0
  135. package/ios/Animations/Interpolators/ANNViewTracks.h +9 -6
  136. package/ios/Animations/Interpolators/ANNViewTracks.mm +100 -30
  137. package/ios/CLAUDE.md +32 -22
  138. package/ios/CORE.md +25 -21
  139. package/ios/Contract/ANNCommandRunner.h +8 -7
  140. package/ios/Contract/ANNCommandRunner.mm +21 -27
  141. package/ios/Contract/ANNLayoutNode.h +3 -3
  142. package/ios/Contract/ANNLayoutReader.h +3 -3
  143. package/ios/Core/ANNAppDelegate.mm +0 -2
  144. package/ios/Core/ANNDeepLinkQueue.h +6 -5
  145. package/ios/Core/ANNDeepLinkQueue.mm +22 -10
  146. package/ios/Core/ANNJavaScriptCalls.h +11 -12
  147. package/ios/Core/ANNJavaScriptCalls.mm +7 -16
  148. package/ios/Core/ANNReloadCoordinator.mm +4 -8
  149. package/ios/Core/ANNSceneDelegate.mm +2 -2
  150. package/ios/Core/ApexNavigation+Internal.h +1 -1
  151. package/ios/Core/ApexNavigation.mm +6 -2
  152. package/ios/Layouts/Arrangement/ANNArrangementState.h +2 -17
  153. package/ios/Layouts/Arrangement/ANNArrangementState.mm +0 -38
  154. package/ios/Layouts/Arrangement/ANNArrangementViewController.mm +4 -4
  155. package/ios/Layouts/Root/ANNRootCoordinator.mm +45 -15
  156. package/ios/Layouts/Screen/ANNComponentViewController.h +2 -2
  157. package/ios/Layouts/Screen/ANNComponentViewController.mm +13 -23
  158. package/ios/Layouts/Screen/ANNPreviewInteraction.h +7 -4
  159. package/ios/Layouts/Screen/ANNPreviewInteraction.mm +72 -10
  160. package/ios/Layouts/Screen/ANNScreenEnvironment.h +63 -0
  161. package/ios/Layouts/Screen/ANNScreenEnvironment.mm +181 -0
  162. package/ios/Layouts/Screen/ANNScreenRegions.h +3 -18
  163. package/ios/Layouts/Screen/ANNScreenRegions.mm +0 -38
  164. package/ios/Layouts/Screen/ANNScreenSafeArea.h +4 -9
  165. package/ios/Layouts/Screen/ANNScreenSafeArea.mm +14 -16
  166. package/ios/Layouts/Stack/ANNPreviewPush.h +7 -6
  167. package/ios/Layouts/Stack/ANNPreviewPush.mm +57 -5
  168. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.h +11 -2
  169. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.mm +14 -7
  170. package/ios/Layouts/Stack/ANNStackController.h +8 -0
  171. package/ios/Layouts/Stack/ANNStackController.mm +153 -11
  172. package/ios/Layouts/Stack/ANNSwipePopInteraction.h +26 -0
  173. package/ios/Layouts/Stack/ANNSwipePopInteraction.mm +185 -0
  174. package/ios/Layouts/Stack/InteractivePopGestureDelegate.mm +28 -4
  175. package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.h +12 -1
  176. package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.mm +23 -0
  177. package/ios/Layouts/Tabs/ANNBottomTabsController.mm +2 -1
  178. package/ios/Layouts/Tabs/ANNBottomTabsCustomRow.mm +8 -3
  179. package/ios/Layouts/Tabs/ANNBottomTabsPresenter.h +4 -0
  180. package/ios/Layouts/Tabs/ANNBottomTabsPresenter.mm +123 -36
  181. package/ios/Layouts/Tabs/ANNTabsDesign.h +6 -5
  182. package/ios/Layouts/Tabs/ANNTabsDesign.mm +9 -1
  183. package/ios/Layouts/Tabs/UITabBar+utils.h +5 -5
  184. package/ios/Layouts/Tabs/UITabBar+utils.mm +32 -13
  185. package/ios/Options/ANNAnimationOptions.h +2 -1
  186. package/ios/Options/ANNAnimationOptions.mm +1 -1
  187. package/ios/Options/ANNBottomTabsOptions.h +2 -0
  188. package/ios/Options/ANNBottomTabsOptions.mm +1 -0
  189. package/ios/Options/ANNOptions.h +25 -0
  190. package/ios/Options/ANNOptions.mm +157 -1
  191. package/ios/Options/ANNOptionsReader.mm +108 -0
  192. package/ios/Options/ANNStackPopAnimationOptions.h +13 -0
  193. package/ios/Options/ANNStackPopAnimationOptions.mm +11 -0
  194. package/ios/Options/Params/ANNParam.h +15 -0
  195. package/ios/Options/Params/ANNParam.mm +61 -0
  196. package/ios/Options/Params/Color.h +3 -0
  197. package/ios/Options/Params/Color.mm +21 -0
  198. package/ios/Options/Params/ColorParser.h +4 -3
  199. package/ios/Options/Params/ColorParser.mm +22 -4
  200. package/ios/Options/Params/Image.h +4 -0
  201. package/ios/Options/Params/Image.mm +20 -0
  202. package/ios/React/ANNReactView.mm +6 -25
  203. package/ios/React/ANNSafeAreaViewComponentView.mm +26 -15
  204. package/ios/React/ANNSurfaceHostingView.h +14 -0
  205. package/ios/React/ANNSurfaceHostingView.mm +144 -1
  206. package/ios/React/Slots/ANNSlotScreenView.mm +8 -2
  207. package/ios/TopBar/ANNBackButtonPresenter.mm +6 -5
  208. package/ios/TopBar/ANNBarAppearance.h +2 -1
  209. package/ios/TopBar/ANNBarAppearance.mm +111 -30
  210. package/ios/TopBar/ANNBarBackgroundComponent.mm +16 -0
  211. package/ios/TopBar/ANNBarButtonComponentView.h +4 -4
  212. package/ios/TopBar/ANNBarButtonComponentView.mm +1 -1
  213. package/ios/TopBar/ANNBarButtons.h +5 -3
  214. package/ios/TopBar/ANNBarButtons.mm +186 -17
  215. package/ios/TopBar/ANNLargeTitlePresenter.mm +24 -4
  216. package/ios/TopBar/ANNMainList.h +3 -0
  217. package/ios/TopBar/ANNMainList.mm +4 -0
  218. package/ios/TopBar/ANNScrollEdgeEffects.h +22 -6
  219. package/ios/TopBar/ANNScrollEdgeEffects.mm +123 -16
  220. package/ios/TopBar/ANNSearchPresenter.mm +2 -2
  221. package/ios/TopBar/ANNSearchResultsViewController.mm +5 -5
  222. package/ios/TopBar/ANNTopBarPresenter.h +3 -2
  223. package/ios/TopBar/ANNTopBarPresenter.mm +95 -22
  224. package/ios/TurboModules/ANNTurboModule.mm +66 -16
  225. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.cpp +20 -0
  226. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.h +5 -14
  227. package/lib/module/ARCHITECTURE.md +17 -7
  228. package/lib/module/adapters/NativeANNTurboModule.js.map +1 -1
  229. package/lib/module/api/app/AppRegistry.js +14 -2
  230. package/lib/module/api/app/AppRegistry.js.map +1 -1
  231. package/lib/module/api/app/createNavigation.js +188 -66
  232. package/lib/module/api/app/createNavigation.js.map +1 -1
  233. package/lib/module/api/events/navigationEvents.js +6 -2
  234. package/lib/module/api/events/navigationEvents.js.map +1 -1
  235. package/lib/module/api/hooks/useSafeAreaInsets.js +4 -3
  236. package/lib/module/api/hooks/useSafeAreaInsets.js.map +1 -1
  237. package/lib/module/api/linking/linking.js +11 -0
  238. package/lib/module/api/linking/linking.js.map +1 -1
  239. package/lib/module/api/options/OptionsChain.js +2 -2
  240. package/lib/module/api/screens/defineScreen.js +45 -3
  241. package/lib/module/api/screens/defineScreen.js.map +1 -1
  242. package/lib/module/api/screens/nativeScreens.js +31 -6
  243. package/lib/module/api/screens/nativeScreens.js.map +1 -1
  244. package/lib/module/api/screens/registerScreens.js +172 -35
  245. package/lib/module/api/screens/registerScreens.js.map +1 -1
  246. package/lib/module/api/theme/theme.js +5 -0
  247. package/lib/module/api/theme/theme.js.map +1 -1
  248. package/lib/module/engine/commands.js +42 -2
  249. package/lib/module/engine/commands.js.map +1 -1
  250. package/lib/module/engine/layout.js +7 -2
  251. package/lib/module/engine/layout.js.map +1 -1
  252. package/lib/module/engine/nativeScreens.js +9 -0
  253. package/lib/module/engine/nativeScreens.js.map +1 -1
  254. package/lib/module/engine/options.js +5 -4
  255. package/lib/module/engine/options.js.map +1 -1
  256. package/lib/module/engine/optionsChange.js +102 -0
  257. package/lib/module/engine/optionsChange.js.map +1 -0
  258. package/lib/module/engine/refresh.js +85 -0
  259. package/lib/module/engine/refresh.js.map +1 -0
  260. package/lib/module/engine/rememberedOptions.js +60 -0
  261. package/lib/module/engine/rememberedOptions.js.map +1 -1
  262. package/lib/module/engine/screens.js +55 -4
  263. package/lib/module/engine/screens.js.map +1 -1
  264. package/lib/typescript/adapters/NativeANNTurboModule.d.ts +7 -0
  265. package/lib/typescript/adapters/NativeANNTurboModule.d.ts.map +1 -1
  266. package/lib/typescript/api/app/AppRegistry.d.ts.map +1 -1
  267. package/lib/typescript/api/app/createNavigation.d.ts +8 -3
  268. package/lib/typescript/api/app/createNavigation.d.ts.map +1 -1
  269. package/lib/typescript/api/events/navigationEvents.d.ts +2 -2
  270. package/lib/typescript/api/events/navigationEvents.d.ts.map +1 -1
  271. package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts +4 -3
  272. package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts.map +1 -1
  273. package/lib/typescript/api/index.d.ts +1 -1
  274. package/lib/typescript/api/index.d.ts.map +1 -1
  275. package/lib/typescript/api/linking/linking.d.ts +8 -0
  276. package/lib/typescript/api/linking/linking.d.ts.map +1 -1
  277. package/lib/typescript/api/options/OptionsChain.d.ts +2 -2
  278. package/lib/typescript/api/screens/defineScreen.d.ts +23 -4
  279. package/lib/typescript/api/screens/defineScreen.d.ts.map +1 -1
  280. package/lib/typescript/api/screens/nativeScreens.d.ts +8 -1
  281. package/lib/typescript/api/screens/nativeScreens.d.ts.map +1 -1
  282. package/lib/typescript/api/screens/registerScreens.d.ts.map +1 -1
  283. package/lib/typescript/api/theme/theme.d.ts +2 -0
  284. package/lib/typescript/api/theme/theme.d.ts.map +1 -1
  285. package/lib/typescript/engine/commands.d.ts +5 -0
  286. package/lib/typescript/engine/commands.d.ts.map +1 -1
  287. package/lib/typescript/engine/layout.d.ts.map +1 -1
  288. package/lib/typescript/engine/nativeScreens.d.ts +5 -0
  289. package/lib/typescript/engine/nativeScreens.d.ts.map +1 -1
  290. package/lib/typescript/engine/optionsChange.d.ts +28 -0
  291. package/lib/typescript/engine/optionsChange.d.ts.map +1 -0
  292. package/lib/typescript/engine/refresh.d.ts +35 -0
  293. package/lib/typescript/engine/refresh.d.ts.map +1 -0
  294. package/lib/typescript/engine/rememberedOptions.d.ts +13 -0
  295. package/lib/typescript/engine/rememberedOptions.d.ts.map +1 -1
  296. package/lib/typescript/engine/screens.d.ts +27 -6
  297. package/lib/typescript/engine/screens.d.ts.map +1 -1
  298. package/lib/typescript/interfaces/ComponentEvents.d.ts +2 -2
  299. package/lib/typescript/interfaces/options/animations.d.ts +44 -14
  300. package/lib/typescript/interfaces/options/animations.d.ts.map +1 -1
  301. package/lib/typescript/interfaces/options/bottomTabs.d.ts +19 -6
  302. package/lib/typescript/interfaces/options/bottomTabs.d.ts.map +1 -1
  303. package/lib/typescript/interfaces/options/buttons.d.ts +10 -10
  304. package/lib/typescript/interfaces/options/modals.d.ts +6 -7
  305. package/lib/typescript/interfaces/options/modals.d.ts.map +1 -1
  306. package/lib/typescript/interfaces/options/stack.d.ts +8 -3
  307. package/lib/typescript/interfaces/options/stack.d.ts.map +1 -1
  308. package/lib/typescript/interfaces/options/system.d.ts +8 -5
  309. package/lib/typescript/interfaces/options/system.d.ts.map +1 -1
  310. package/lib/typescript/interfaces/options/toolbar.d.ts +2 -2
  311. package/lib/typescript/interfaces/options/topBar.d.ts +46 -29
  312. package/lib/typescript/interfaces/options/topBar.d.ts.map +1 -1
  313. package/metro/acceptPlugin.js +57 -0
  314. package/metro/babelTransformer.js +45 -0
  315. package/metro/index.js +36 -0
  316. package/package.json +3 -1
  317. package/src/ARCHITECTURE.md +17 -7
  318. package/src/adapters/NativeANNTurboModule.ts +7 -0
  319. package/src/api/app/AppRegistry.ts +16 -2
  320. package/src/api/app/createNavigation.ts +201 -69
  321. package/src/api/events/navigationEvents.ts +9 -3
  322. package/src/api/hooks/useSafeAreaInsets.ts +4 -3
  323. package/src/api/index.ts +1 -0
  324. package/src/api/linking/linking.ts +22 -1
  325. package/src/api/options/OptionsChain.ts +2 -2
  326. package/src/api/screens/defineScreen.ts +49 -5
  327. package/src/api/screens/nativeScreens.ts +40 -4
  328. package/src/api/screens/registerScreens.tsx +170 -42
  329. package/src/api/theme/theme.ts +5 -0
  330. package/src/engine/commands.ts +51 -6
  331. package/src/engine/layout.ts +11 -2
  332. package/src/engine/nativeScreens.ts +10 -1
  333. package/src/engine/options.ts +6 -8
  334. package/src/engine/optionsChange.ts +107 -0
  335. package/src/engine/refresh.ts +97 -0
  336. package/src/engine/rememberedOptions.ts +70 -0
  337. package/src/engine/screens.tsx +53 -8
  338. package/src/interfaces/ComponentEvents.ts +2 -2
  339. package/src/interfaces/options/animations.ts +44 -14
  340. package/src/interfaces/options/bottomTabs.ts +19 -6
  341. package/src/interfaces/options/buttons.ts +10 -10
  342. package/src/interfaces/options/modals.ts +6 -7
  343. package/src/interfaces/options/stack.ts +8 -3
  344. package/src/interfaces/options/system.ts +8 -5
  345. package/src/interfaces/options/toolbar.ts +2 -2
  346. package/src/interfaces/options/topBar.ts +46 -29
  347. package/android/src/main/java/dev/apexnative/navigation/react/ArrangementStates.kt +0 -42
  348. package/android/src/main/java/dev/apexnative/navigation/react/ScreenInsets.kt +0 -70
  349. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowPlacer.kt +0 -223
  350. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStub.kt +0 -31
  351. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMatrixAnimator.kt +0 -136
  352. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PlainViewAnimator.kt +0 -86
  353. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PropertyAnimatorCreator.kt +0 -33
  354. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ReactImageAnimator.kt +0 -64
  355. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextChangeAnimator.kt +0 -177
  356. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewChangeAnimator.kt +0 -137
  357. package/ios/Layouts/Screen/ANNScreenInsets.h +0 -30
  358. package/ios/Layouts/Screen/ANNScreenInsets.mm +0 -70
@@ -2,6 +2,7 @@
2
2
  #import "ANNAnimationPropertyOptions.h"
3
3
  #import "ANNElementTransitionOptions.h"
4
4
  #import "ANNTrack.h"
5
+ #import "ANNTransformParts.h"
5
6
  #import "ANNUtils.h"
6
7
  #import "ANNViewAnimationOptions.h"
7
8
  #import <QuartzCore/QuartzCore.h>
@@ -81,10 +82,19 @@ static ANNTrack *ANNTrackOf(Double *from, Double *to, Double *duration, Double *
81
82
  CGPoint _origin;
82
83
  CGFloat _alphaBefore;
83
84
  CATransform3D _transformBefore;
85
+ // The parts of the view's own transform (its React Native `transform`): what a property that doesn't play keeps,
86
+ // and the missing end of one that does, as Android keeps a view's own properties.
87
+ CGPoint _ownTranslation;
88
+ CGPoint _ownScale;
89
+ double _ownRotationX;
90
+ double _ownRotationY;
91
+ double _ownRotation;
92
+ CATransform3D _ownSkew;
93
+ CGFloat _ownPerspective;
84
94
  BOOL _animatesTransform;
85
95
  BOOL _tilts;
86
- BOOL _wroteAlpha;
87
- BOOL _wroteTransform;
96
+ BOOL _addedAlpha;
97
+ BOOL _addedTransform;
88
98
  BOOL _restored;
89
99
  NSTimeInterval _endTime;
90
100
  }
@@ -146,21 +156,48 @@ static ANNTrack *ANNTrackOf(Double *from, Double *to, Double *duration, Double *
146
156
  layer.position.y - bounds.size.height * layer.anchorPoint.y);
147
157
  _alphaBefore = alphaBefore;
148
158
  _transformBefore = layer.transform;
159
+ [self readOwnTransform];
149
160
  }
150
161
  return self;
151
162
  }
152
163
 
164
+ // A transform that can't be split (a scale of 0) counts as none, as before the view's own transform was kept.
165
+ - (void)readOwnTransform {
166
+ _ownScale = CGPointMake(1, 1);
167
+ _ownSkew = CATransform3DIdentity;
168
+ ANNTransformParts parts;
169
+ if (!ANNTransformPartsOf(_transformBefore, &parts)) {
170
+ return;
171
+ }
172
+ _ownTranslation = CGPointMake((CGFloat)parts.translate[0], (CGFloat)parts.translate[1]);
173
+ _ownScale = CGPointMake((CGFloat)parts.scale[0], (CGFloat)parts.scale[1]);
174
+ ANNRotationDegreesOf(parts, &_ownRotationX, &_ownRotationY, &_ownRotation);
175
+ _ownSkew = ANNSkewTransformOf(parts);
176
+ _ownPerspective = (CGFloat)parts.perspective[2];
177
+ }
178
+
153
179
  - (double)viewValueOf:(ANNViewProperty)property {
154
180
  switch (property) {
155
181
  case ANNViewPropertyX:
156
- return _origin.x;
182
+ return _origin.x + _ownTranslation.x;
157
183
  case ANNViewPropertyY:
158
- return _origin.y;
184
+ return _origin.y + _ownTranslation.y;
185
+ case ANNViewPropertyTranslationX:
186
+ return _ownTranslation.x;
187
+ case ANNViewPropertyTranslationY:
188
+ return _ownTranslation.y;
159
189
  case ANNViewPropertyAlpha:
160
190
  return _alphaBefore;
161
191
  case ANNViewPropertyScaleX:
192
+ return _ownScale.x;
162
193
  case ANNViewPropertyScaleY:
163
- return 1;
194
+ return _ownScale.y;
195
+ case ANNViewPropertyRotationX:
196
+ return _ownRotationX;
197
+ case ANNViewPropertyRotationY:
198
+ return _ownRotationY;
199
+ case ANNViewPropertyRotation:
200
+ return _ownRotation;
164
201
  default:
165
202
  return 0;
166
203
  }
@@ -198,17 +235,9 @@ static ANNTrack *ANNTrackOf(Double *from, Double *to, Double *duration, Double *
198
235
  return track ? [track valueAt:time] : [self viewValueOf:property];
199
236
  }
200
237
 
201
- - (void)applyAtTime:(NSTimeInterval)time {
202
- if (_restored) {
203
- return;
204
- }
205
- if (self.animatesAlpha) {
206
- _view.alpha = (CGFloat)[_tracks[ANNViewPropertyAlpha] valueAt:time];
207
- _wroteAlpha = YES;
208
- }
209
- if (!_animatesTransform) {
210
- return;
211
- }
238
+ // The view's transform at `time`: every property of the transform at its value then, the ones that don't play at the
239
+ // view's own.
240
+ - (CATransform3D)transformAtTime:(NSTimeInterval)time {
212
241
  CGFloat scaleX = (CGFloat)[self valueOf:ANNViewPropertyScaleX at:time];
213
242
  CGFloat scaleY = (CGFloat)[self valueOf:ANNViewPropertyScaleY at:time];
214
243
  // The translation wins over the place when a side has both.
@@ -221,28 +250,69 @@ static ANNTrack *ANNTrackOf(Double *from, Double *to, Double *duration, Double *
221
250
  ? (CGFloat)[self valueOf:ANNViewPropertyTranslationY at:time]
222
251
  : (CGFloat)([self valueOf:ANNViewPropertyY at:time] - _origin.y);
223
252
  // `CATransform3D` multiplies row vectors: each step below comes after the ones before it.
224
- CATransform3D transform = CATransform3DMakeScale(scaleX, scaleY, 1);
225
- if (_tracks[ANNViewPropertyRotationX]) {
253
+ CATransform3D transform =
254
+ CATransform3DConcat(CATransform3DMakeScale(scaleX, scaleY, 1), _ownSkew);
255
+ if (_tracks[ANNViewPropertyRotationX] || _ownRotationX != 0) {
226
256
  CGFloat radians = ANNRadians([self valueOf:ANNViewPropertyRotationX at:time]);
227
257
  transform = CATransform3DConcat(transform, ANNRotationX(radians));
228
258
  }
229
- if (_tracks[ANNViewPropertyRotationY]) {
259
+ if (_tracks[ANNViewPropertyRotationY] || _ownRotationY != 0) {
230
260
  CGFloat radians = ANNRadians([self valueOf:ANNViewPropertyRotationY at:time]);
231
261
  transform = CATransform3DConcat(transform, ANNRotationY(radians));
232
262
  }
233
- if (_tracks[ANNViewPropertyRotation]) {
263
+ if (_tracks[ANNViewPropertyRotation] || _ownRotation != 0) {
234
264
  CGFloat radians = ANNRadians([self valueOf:ANNViewPropertyRotation at:time]);
235
265
  transform = CATransform3DConcat(transform, ANNRotationZ(radians));
236
266
  }
237
- if (_tilts) {
267
+ // A tilt that plays gets the camera's perspective unless the view has its own; a view's own tilt keeps the
268
+ // perspective it had, none without one, as React Native draws it.
269
+ if (_tilts || _ownPerspective != 0) {
238
270
  CATransform3D perspective = CATransform3DIdentity;
239
- perspective.m34 = -1.0 / ANNCameraDistance();
271
+ perspective.m34 = _ownPerspective != 0 ? _ownPerspective : -1.0 / ANNCameraDistance();
240
272
  transform = CATransform3DConcat(transform, perspective);
241
273
  }
242
- transform = CATransform3DConcat(transform,
243
- CATransform3DMakeTranslation(translationX, translationY, 0));
244
- _view.layer.transform = transform;
245
- _wroteTransform = YES;
274
+ return CATransform3DConcat(transform,
275
+ CATransform3DMakeTranslation(translationX, translationY, 0));
276
+ }
277
+
278
+ - (void)addAnimationsWithLength:(NSTimeInterval)length {
279
+ if (_restored || !self.hasTracks) {
280
+ return;
281
+ }
282
+ // Every track's start and end is a sample, so a track that starts late or ends early does it on time.
283
+ NSMutableArray<NSNumber *> *marks = [NSMutableArray new];
284
+ for (NSInteger index = 0; index < ANNViewPropertyCount; index++) {
285
+ ANNTrack *track = _tracks[index];
286
+ if (track) {
287
+ [marks addObject:@(track.delay)];
288
+ [marks addObject:@(track.endTime)];
289
+ }
290
+ }
291
+ NSArray<NSNumber *> *times = ANNSampleTimes(_endTime, length, marks);
292
+ CALayer *layer = _view.layer;
293
+ if (self.animatesAlpha) {
294
+ NSMutableArray<NSNumber *> *values = [NSMutableArray arrayWithCapacity:times.count];
295
+ for (NSNumber *time in times) {
296
+ [values addObject:@([_tracks[ANNViewPropertyAlpha] valueAt:time.doubleValue])];
297
+ }
298
+ CAKeyframeAnimation *animation = ANNKeyframes(@"opacity", values, times, length);
299
+ if (animation) {
300
+ [layer addAnimation:animation forKey:ANNAnimationKey(@"opacity")];
301
+ _addedAlpha = YES;
302
+ }
303
+ }
304
+ if (_animatesTransform) {
305
+ NSMutableArray<NSValue *> *values = [NSMutableArray arrayWithCapacity:times.count];
306
+ for (NSNumber *time in times) {
307
+ CATransform3D transform = [self transformAtTime:time.doubleValue];
308
+ [values addObject:[NSValue valueWithCATransform3D:transform]];
309
+ }
310
+ CAKeyframeAnimation *animation = ANNKeyframes(@"transform", values, times, length);
311
+ if (animation) {
312
+ [layer addAnimation:animation forKey:ANNAnimationKey(@"transform")];
313
+ _addedTransform = YES;
314
+ }
315
+ }
246
316
  }
247
317
 
248
318
  - (void)restore {
@@ -250,11 +320,11 @@ static ANNTrack *ANNTrackOf(Double *from, Double *to, Double *duration, Double *
250
320
  return;
251
321
  }
252
322
  _restored = YES;
253
- if (_wroteAlpha) {
254
- _view.alpha = _alphaBefore;
323
+ if (_addedAlpha) {
324
+ [_view.layer removeAnimationForKey:ANNAnimationKey(@"opacity")];
255
325
  }
256
- if (_wroteTransform) {
257
- _view.layer.transform = _transformBefore;
326
+ if (_addedTransform) {
327
+ [_view.layer removeAnimationForKey:ANNAnimationKey(@"transform")];
258
328
  }
259
329
  }
260
330
 
package/ios/CLAUDE.md CHANGED
@@ -17,7 +17,7 @@ Swift is not used here: apps reach the core through the public headers (`Public/
17
17
  - `Contract/`: The command path: runner, answer, layout reader and nodes, validator, error texts, tree options.
18
18
  - `Core/`: The spine: node protocol and helper, registry, dispatcher, state, render wait, parking, system UI, reload, event emitter, start (`ApexNavigation.mm`, `ANNAppDelegate.mm`), and the modules `ANNKeyCommands`, `ANNDeepLinkQueue`, `ANNHinge`, `ANNSceneDelegate.mm`.
19
19
  - `Layouts/Root/`: `ANNRootCoordinator` (`setRoot`), `ANNLayoutFactory`, `ANNSplashViewController`.
20
- - `Layouts/Screen/`: The screen (`ANNComponentViewController`), its presenter, readiness, insets, regions, safe-area math, the main list rule, previews.
20
+ - `Layouts/Screen/`: The screen (`ANNComponentViewController`), its presenter, readiness, its environment for JS (`ANNScreenEnvironment`), regions, safe-area math, the main list rule, previews.
21
21
  - `Layouts/External/`: Native screens: `ANNExternalViewController`, `ANNNativeScreenCalls`.
22
22
  - `Layouts/Stack/`: `ANNStackController`, `ANNStackQueue`, `ANNStackCommands`, `ANNStackPresenter`, `ANNPreviewPush`, the swipe-back delegate.
23
23
  - `Layouts/Tabs/`: `ANNBottomTabsController`, its presenter, item builder, custom row, preload window, More delegate, long press, dots.
@@ -25,7 +25,7 @@ Swift is not used here: apps reach the core through the public headers (`Public/
25
25
  - `Layouts/Overlay/`: `ANNOverlayCoordinator`, `ANNOverlayWindow`.
26
26
  - `Layouts/SideMenu/`: The side menu module and its presenter and wrapper.
27
27
  - `Layouts/SplitView/`: The split view module, plus the core's `ANNSplitViewPresenter` and `ANNSplitViewCommands`.
28
- - `Layouts/Arrangement/`: The pair (iOS 27.1): `ANNArrangementViewController`, `ANNArrangementState`.
28
+ - `Layouts/Arrangement/`: The pair (iOS 27.1): `ANNArrangementViewController`, `ANNArrangementState` (whether pairs can show).
29
29
  - `TopBar/`: The bar of a screen: title, buttons, back button, large title, appearance, search, toolbar, edge effects.
30
30
  - `Options/`, `Options/Params`: One `ANN<Group>Options` class per group, the field table, the value kinds and parsers (`Bool`, `Color`, `Text`, `Image`, …), the images' cache and loader (`ANNOptionImages`).
31
31
  - `Animations/`: The custom transition engine: plan, animator, wait, frame driver, rules; `Elements/` and `Interpolators/`.
@@ -42,9 +42,9 @@ Top-level files: `Package.swift` (SwiftPM; `headerFolders` lists every folder wh
42
42
  - Launch, the app-facing API — `Public/ApexNavigation/`; `Core/`: `ApexNavigation.mm`, `ANNAppDelegate.mm`, `ANNSceneDelegate.mm`, `ApexNavigation+Internal.h`
43
43
  - Root, splash, reload — `Layouts/Root/`: `ANNRootCoordinator`, `ANNSplashViewController`; `Core/`: `ANNReloadCoordinator`
44
44
  - Screen: React root, slot, native screen — `Layouts/Screen/`: `ANNComponentViewController`; `React/`: `ANNReactView`, `ANNReactViewCreator`, `Slots/`; `Layouts/External/`
45
- - Screen: insets, background, keyboard focus — `Layouts/Screen/`: `ANNScreenInsets`, `ANNScreenSafeArea`, `ANNScreenBars`, `ANNScreenPlace` (the safe area of a parked screen), `ANNComponentPresenter` (background, status bar blur), `ANNComponentViewController` (key commands)
45
+ - Screen: insets, background, keyboard focus — `Layouts/Screen/`: `ANNScreenEnvironment`, `ANNScreenSafeArea`, `ANNScreenBars`, `ANNScreenPlace` (the safe area of a parked screen), `ANNComponentPresenter` (background, status bar blur), `ANNComponentViewController` (key commands)
46
46
  - Safe area view — `React/`: `ANNSafeAreaViewComponentView`; `Layouts/Screen/`: `ANNScreenReadiness`; `cpp/`
47
- - Stack: queue, commands, back, gestures — `Layouts/Stack/`: `ANNStackQueue`, `ANNStackCommands`, `ANNStackController`, `InteractivePopGestureDelegate`, `ANNStackAnimatingDelegate`
47
+ - Stack: queue, commands, back, gestures — `Layouts/Stack/`: `ANNStackQueue`, `ANNStackCommands`, `ANNStackController`, `InteractivePopGestureDelegate`, `ANNStackAnimatingDelegate`, `ANNSwipePopInteraction`
48
48
  - Top bar: title, buttons, menus, large title — `TopBar/`: `ANNTopBarPresenter`, `ANNBarButtons`, `ANNBarAppearance`, `ANNLargeTitlePresenter`, `ANNBackButtonPresenter`, `ANNTitleView`, `ANNTitleGlassView`
49
49
  - Top bar: components, waits — `TopBar/`: `ANNBarComponentsWait`, `ANNBarBackgroundComponent`, `ANNTitleComponentView`, `ANNBarButtonComponentView`; `React/`: `ANNReactComponentRegistry`
50
50
  - Search — `TopBar/`: `ANNSearchPresenter`, `ANNSearchResultsViewController`
@@ -63,27 +63,29 @@ Top-level files: `Package.swift` (SwiftPM; `headerFolders` lists every folder wh
63
63
  - Error texts and answers — `Contract/`: `ANNErrorTexts` and `ANNCommandContract` (made from `src/interfaces/contract/errors.json` and `commands.json` by `scripts/contract.mjs`); `Core/`: `ANNErrorHandler`
64
64
  - Links — `Core/`: `ANNDeepLinkQueue`; the `getLaunchLink` method of `ANNTurboModule`
65
65
  - Key commands — `Core/`: `ANNKeyCommands`; `Layouts/Screen/`: `ANNComponentViewController`
66
- - Hinge, regions — `Core/`: `ANNHinge`; `Layouts/Screen/`: `ANNScreenRegions`; `Layouts/Arrangement/`: `ANNArrangementState`
66
+ - Hinge, regions, arrangement — `Core/`: `ANNHinge`; `Layouts/Screen/`: `ANNScreenRegions` (the measuring), `ANNScreenEnvironment` (what JS reads); `Layouts/Arrangement/`: `ANNArrangementState`
67
67
  - Native screens — `Layouts/External/`: `ANNExternalViewController`, `ANNNativeScreenCalls`; `Layouts/Screen/ANNNativeScreenContext.mm`
68
68
  - Slots — `React/Slots/`: `ANNSlotHost`, `ANNSlotContainers` (containers and slot views by slot id: a change goes
69
69
  straight to the views of its id), `ANNSlotScreenView`, `ANNSlotComponentView`; `cpp/`
70
70
 
71
71
  ## Threads
72
72
 
73
- - **Module queue:** the layout check (`ANNLayoutReader`) and the sync getters. The check reads only stores safe from
74
- any thread (`ApexNavigation hasNativeScreenNamed:`, `ANNArrangementState canShowArrangements`).
75
- - **Main queue:** everything else. A command body starts with `ANNAssertMainQueue()`. The options of a layout are parsed
76
- here (`ANNLayoutTreeOptions`; an image keeps only its source). `ANNEventEmitter` moves an event from another queue
77
- to the main queue.
73
+ - **Main queue:** everything but the sync getters and the images. `ANNTurboModule`'s method queue is the main queue,
74
+ as `ANNTurboEventEmitter`'s: an async method comes there from the JavaScript thread, and `ANNCommandRunner` runs the
75
+ layout check (`ANNLayoutReader`) and the body in that one task. A command body starts with `ANNAssertMainQueue()`.
76
+ The options of a layout are parsed here (`ANNLayoutTreeOptions`; an image keeps only its source). `ANNEventEmitter`
77
+ moves an event from another queue to the main queue.
78
78
  - **The images' queue** (`ANNOptionImages`, `Options/Params`): every option image decodes there, through one cache.
79
79
  An element that shows an image asks for it when it applies and waits for it (the first frame needs it); only a tab
80
80
  item's new icon on the bar that shows comes later (`ANNBottomTabsPresenter`), the last build of the item winning.
81
- - **Sync getters** answer JS during a screen's first render: `getScreenInsets`, `getScreenRegions`,
82
- `getArrangementState`, `getHinge`, `getStartInfo`. They read `ANNScreenInsets`, `ANNScreenRegions`,
83
- `ANNArrangementState`, `ANNHinge lastValue`, written on the main queue and guarded by `@synchronized`.
81
+ - **Sync getters** answer JS on the JavaScript thread (React Native calls them there whatever the module's queue)
82
+ during a screen's first render: `getScreenInsets`, `getScreenRegions`, `getArrangementState`, `getHinge`,
83
+ `getStartInfo`. They read `ANNScreenEnvironment` (one record per screen id: insets, padding, regions, arrangement)
84
+ and `ANNHinge lastValue`, written on the main queue and guarded by `@synchronized`. The environment's padding
85
+ listeners are main-queue only.
84
86
  `ANNReloadCoordinator.generation` and `ANNEventEmitter.isCurrent` are readable from any thread.
85
87
  - **After the calls of JavaScript:** `ANNJavaScriptCalls afterCallsMadeSoFar:` runs a step on the main queue after
86
- every call JavaScript made by then, by the calls' own way (the JavaScript thread, the module's queue, the main
88
+ every call JavaScript made by then, by the calls' own way (a task on the JavaScript thread, then one on the main
87
89
  queue). A push's wait ends through it, so the `mergeOptions` of its screen's first commit come first.
88
90
 
89
91
  ## Checks
@@ -91,8 +93,8 @@ Top-level files: `Package.swift` (SwiftPM; `headerFolders` lists every folder wh
91
93
  - `scripts/build-ios.sh`: 0 warnings in `ios/` (warnings fail it). It builds the Showcase for the simulator.
92
94
  - A new file needs `scripts/pods.sh` first (CocoaPods globs `ios/**`). A new folder also goes into `headerFolders` of
93
95
  `Package.swift`, because files import each other's headers by bare name.
94
- - There is no iOS unit-test target. `ANNSystemUIRulesSelfCheck` and `ANNCheckOptionClassesFrom` run once in DEBUG; the
95
- rest is checked by the Showcase scenarios.
96
+ - There is no iOS unit-test target. `ANNSystemUIRulesSelfCheck`, `ANNCheckOptionClassesFrom` and `ANNCheckSameValues`
97
+ (the options' value equality) run once in DEBUG; the rest is checked by the Showcase scenarios.
96
98
  - Format by hand: `.claude/rules/code-objc.md`.
97
99
 
98
100
  ## Pitfalls
@@ -137,10 +139,17 @@ Top-level files: `Package.swift` (SwiftPM; `headerFolders` lists every folder wh
137
139
  (the root, a modal, an overlay: their record is listed and parked by then), and the modal's end steps inside UIKit's
138
140
  completions and delegate calls (`protectEndOf:showing:step:`, `protectBatch:step:`); the overlay's guard is
139
141
  `protectWaitOf:step:`.
140
- - Each step of a transition's element (a pair's start and take-off, an element's start, every frame and restore
142
+ - Each step of a transition's element (a pair's start and take-off, an element's start, its animations and restore
141
143
  through `ANNIsolatedElement`) runs in `ANNElementStep`: an exception skips that element only. A new step of an
142
- element goes there too, or one bad element stops the transition (a frame's exception ends the app). The elements of
143
- a transition are found in one walk per screen (`ANNTransitionViews`).
144
+ element goes there too, or one bad element stops the transition. The elements of a transition are found in one walk
145
+ per screen (`ANNTransitionViews`).
146
+ - A custom transition runs in Core Animation (`ANNFrameDriver`): each client samples its values once, at the start,
147
+ into keyframe animations under the core's keys (`ANNAnimationKey`), and `restore` removes them. It never writes a
148
+ view's own alpha or transform for a frame; a value the core writes for the transition (the arriving view's hide, a
149
+ hidden flag, a depth) goes back as before. A pop that follows the swipe back also stops the time of the transition's
150
+ container (`startPausedOn:done:`), and the container gets its time back before the clients restore. UIKit runs its
151
+ swipe back without asking the navigation's delegate for a transition (iOS 26 checked), so that pop follows the
152
+ stack's own swipe from the leading edge, and UIKit's swipes stand aside meanwhile (`swipeBackTakes:`).
144
153
  - An `ANNCommandAnswer` that goes away unanswered rejects (`notAnswered:`), but only once nothing holds it: a record,
145
154
  list or queue that keeps an answer still answers it on every exit, or the promise waits as long as the record lives.
146
155
  - On iOS 26 UIKit draws a screen's large title, for a whole pop or swipe back, inside the scroll view the bar follows
@@ -150,9 +159,10 @@ Top-level files: `Package.swift` (SwiftPM; `headerFolders` lists every folder wh
150
159
  - Under a hidden bar UIKit's swipe delegate refuses the swipes in questions of its own: `InteractivePopGestureDelegate`
151
160
  stops passing those on while the bar is hidden (`barHidden`, set again on the recognizer at each change, from
152
161
  `swipeBackFollowsBar`), and the core sorts the pans itself.
153
- - UIKit works out the safe area of the window's root view from where it is drawn: a `transform` that moves it (a
154
- root's own `enter`) leaves it with no top inset, and putting the transform back doesn't work it out again. Lay the
155
- root out after a restore (`+[ANNRootCoordinator stopAnimationOf:]`).
162
+ - UIKit works out the safe area of the window's root view from where it is: a `transform` written on it that moves it
163
+ leaves it with no top inset, and putting the transform back doesn't work it out again. A root's own `enter` moves
164
+ only what Core Animation draws; the root is still laid out after a restore (`+[ANNRootCoordinator stopAnimationOf:]`).
165
+ While it animates, the new root takes no touches: it is drawn elsewhere than where it is.
156
166
  - UIKit's `hidesBarsWhenKeyboardAppears`, once on, keeps hiding the bar after it is set back to `NO`: the stack hides
157
167
  the bars for `topBar.hideOnKeyboard` itself (`keyboardWillShow:` / `keyboardDidHide:` of `ANNStackController`) and
158
168
  leaves the flag off.
package/ios/CORE.md CHANGED
@@ -8,10 +8,10 @@ and files is `ios/CLAUDE.md`.
8
8
 
9
9
  ```
10
10
  JS ── ANNTurboModule (codegen ApexNavigationSpec) ────────────────────────────────────────────┐ sync getters
11
- │ module queue │ read stores
11
+ │ main queue (the module's queue), one task per command, in call order │ read stores
12
12
  ▼ ▼ (@synchronized)
13
13
  ANNCommandRunner ── ANNLayoutReader (check the whole layout) ── ANNErrorTexts ── ANNErrorHandler
14
- │ one task per command on the main queue, in call order
14
+ │ the check passed: the body, in the same task
15
15
  ▼
16
16
  area command (ANNStackCommands, ANNRootCoordinator, ANNModalCoordinator, ANNOverlayCoordinator, ANNSplitViewCommands)
17
17
  │ ANNLayoutValidator · ANNLayoutTreeOptions · ANNLayoutFactory ── ANNNodeRegistry
@@ -32,12 +32,13 @@ JS ── ANNTurboModule (codegen ApexNavigationSpec) ────────
32
32
  One line per layer. Each layer calls the next one down, and the answer and the events come back up through the
33
33
  dispatcher.
34
34
 
35
- - **Way in** (`ANNTurboModule`): the codegen methods. An async method hands its work to `ANNCommandRunner`; a sync
36
- getter reads a store and never touches the main queue.
35
+ - **Way in** (`ANNTurboModule`): the codegen methods. Its method queue is the main queue: an async method comes there
36
+ from the JavaScript thread and hands its work to `ANNCommandRunner`; a sync getter runs on the JavaScript thread,
37
+ reads a store and never touches the main queue.
37
38
  - **Layout check** (`ANNLayoutReader`, `ANNLayoutNode`): reads the JSON into immutable nodes and checks the whole
38
39
  tree before any view exists. The first error is the rejection text.
39
- - **Command runner** (`ANNCommandRunner`, `ANNCommandAnswer`): takes the generation of the JavaScript, runs the check on
40
- the module queue, then runs the body on the main queue inside an exception guard. The answer resolves or rejects once.
40
+ - **Command runner** (`ANNCommandRunner`, `ANNCommandAnswer`): takes the generation of the JavaScript, runs the check,
41
+ then the body inside an exception guard, both in the command's one task on the main queue. The answer resolves or rejects once.
41
42
  - **Registry and factory** (`ANNNodeRegistry`, `ANNLayoutFactory`): the factory turns a checked tree into view
42
43
  controllers and registers every node by id.
43
44
  - **Nodes** (`ANNLayoutProtocol`, `UIViewController+LayoutProtocol`, `ANNNodeHelper`): the view controllers. Each holds
@@ -58,20 +59,21 @@ dispatcher.
58
59
  `navigation.push('Profile')` from Home: JS builds a layout node `{ id, type: 'Component', data, children }`, and calls
59
60
  `push(commandId, componentId, layout)`.
60
61
 
61
- 1. **`ANNTurboModule push:componentId:layout:resolve:reject:`** (module queue). Builds the failure text
62
- (`could not push the screen '…'`) and calls `+[ANNCommandRunner run:…]` with a check block and a body block.
63
- 2. **`ANNCommandRunner`** (module queue). Takes `ANNReloadCoordinator.generation`. Runs the check:
62
+ 1. **`ANNTurboModule push:componentId:layout:resolve:reject:`** (main queue, the module's queue: React Native sends
63
+ the call there from the JavaScript thread). Builds the failure text (`could not push the screen '…'`) and calls
64
+ `+[ANNCommandRunner run:…]` with a check block and a body block.
65
+ 2. **`ANNCommandRunner`** (the same task). Takes `ANNReloadCoordinator.generation`. Runs the check:
64
66
  `+[ANNLayoutReader nodeFrom:error:]` reads and validates the whole tree into `ANNLayoutNode`s. A failure rejects here,
65
- through `ANNErrorHandler`, and nothing is queued. Otherwise it makes the `ANNCommandAnswer` and hands one task to the
66
- main queue.
67
- 3. **Main queue.** The task does nothing when the JavaScript went (`answer.isCurrent`), rejects
67
+ through `ANNErrorHandler`, and nothing is made. Otherwise it makes the `ANNCommandAnswer`.
68
+ 3. **The body.** The runner does nothing when the JavaScript went (`answer.isCurrent`), rejects
68
69
  `+[ANNErrorTexts nowhereToShow]` when there is no window, then runs the body in `@try`. The body finds Home in
69
70
  `ANNNodeRegistry` and calls `+[ANNStackCommands push:componentId:what:answer:]`.
70
71
  4. **`ANNStackCommands`.** Finds the stack by walking `layoutParent`; checks `ANNLayoutValidator` (an id already shown,
71
72
  what a stack takes); reads the options of the whole tree with `ANNLayoutTreeOptions` (an image keeps its source,
72
73
  loaded through `ANNOptionImages` when an element shows it); checks `ANNLayoutFactory canMakeTrees:`; a node with
73
- `preview.nativeID` goes to `ANNPreviewPush`; a `key` of an entry below goes back to that entry; else
74
- `+[ANNLayoutFactory nodeFromLayout:options:]` makes Profile (an
74
+ `preview.nativeID` goes to `ANNPreviewPush` (it makes the node at once; a React screen with a root of its own
75
+ renders at the press, in the configuration call of `ANNPreviewInteraction`, other screens at once); a `key` of an
76
+ entry below goes back to that entry; else `+[ANNLayoutFactory nodeFromLayout:options:]` makes Profile (an
75
77
  `ANNComponentViewController` with an `ANNComponentPresenter`, content from `ANNReactViewCreator`) and registers it.
76
78
  No view is rendered yet.
77
79
  5. **`-[ANNStackQueue push:answer:…]`.** The node joins `entries` now (every check reads `entries`), the operation is
@@ -80,7 +82,7 @@ dispatcher.
80
82
  `ANNRenderWait`: unset, for the content at most 0.5 s, with `true` as long as it takes, then for the bar components
81
83
  (their limits from the wait's start when unset, from the content's end with `true`; the screen is parked unseen in
82
84
  the stack's view by `ANNParking`, `stackPark:`); the content's end, content there already too, waits for the calls
83
- JavaScript made by then (`ANNJavaScriptCalls`: the JavaScript thread, the module's queue, the main queue), so the
85
+ JavaScript made by then (`ANNJavaScriptCalls`: the JavaScript thread, then the main queue), so the
84
86
  options of the screen's first commit are in the bar; with `false` nothing. Then it renders the node, drives the appearance of Home and Profile (`+[ANNAppearanceDispatcher driveAppearanceOf:]`), and calls
85
87
  `+[ANNAppearanceDispatcher beginTransitionShowing:]`. Profile's `ComponentWillAppear` is sent now (held until its
86
88
  content mounted, 0.5 s at most). `stackChange:` pushes in UIKit; with an own animation `ANNTransitionPlan` and
@@ -115,8 +117,8 @@ How the others differ:
115
117
 
116
118
  Each of these owns one rule. Call it; do not copy it.
117
119
 
118
- - `ANNCommandRunner`: The one path of every async command: generation, check, main queue, exception guard. Called by: `ANNTurboModule`.
119
- - `ANNLayoutReader`: The layout check, depth first, the same order and texts as Android. Module queue. Called by: The runner's check blocks.
120
+ - `ANNCommandRunner`: The one path of every async command: main queue (the module's queue), generation, check, exception guard. Called by: `ANNTurboModule`.
121
+ - `ANNLayoutReader`: The layout check, depth first, the same order and texts as Android. Main queue, before the body. Called by: The runner's check blocks.
120
122
  - `ANNCommandAnswer`: The answer: state (one step per answer, `reportStateNow`, asked by the end of its transition or by `resolve:`), then promise, then `ANN.CommandCompleted`; once; silent for a JavaScript that went. Called by: Every coordinator and queue.
121
123
  - `ANNNodeRegistry`: Every node by id, weakly. Filled by the factory, cleared at a reload. Called by: Commands, modules, `findViewController:`.
122
124
  - `ANNLayoutFactory`: The core code that names module classes (`ANNSplitViewController`, `ANNSideMenuViewController`, `ANNArrangementViewController`); `ANNSideMenuPresenter` is the one other file that does. One maker per layout type; registers each node. Called by: Every command that shows a layout.
@@ -137,7 +139,7 @@ Each of these owns one rule. Call it; do not copy it.
137
139
  - `ANNReloadCoordinator`: The generation of the JavaScript; the reset after a reload. Called by: Runner, emitter, answer.
138
140
  - Stack answer id: `ANNStackAnswerIdOf(entry, command)` in `ANNStackQueue.h`: the id a stack command answers with. `push` answers the node's own id (a pair's id); every other command, the entry's options screen (a pair's primary). Called by: The queue, `ANNStackCommands`, `ANNPreviewPush`, `ANNSplitViewCommands`.
139
141
  - Waited screens: `waitedComponentViewControllers`: the screens a wait is about (a pair: the ones it puts in the window). `ANNStackScreensOfEntry` is every screen of an entry, for what means all of them. Called by: `ANNRenderWait` owners: root, stack queue, modals, overlays, `ANNSplitViewCommands`.
140
- - Back: The stack: `ANNStackController` (`userGoBackTo:`, `backAction`, the hold) and `InteractivePopGestureDelegate`; UIKit's own pops are followed by `ANNStackQueue uikitShows:`. Called by: UIKit, the user.
142
+ - Back: The stack: `ANNStackController` (`userGoBackTo:`, `backAction`, the hold) and `InteractivePopGestureDelegate`; UIKit's own pops are followed by `ANNStackQueue uikitShows:`. A top whose own pop is `interactive` gets the stack's own swipe from the leading edge instead of UIKit's (UIKit runs its swipe without asking the delegate for a transition): `swipeBackTakes:` picks the swipe, `ownSwipeBack:` pops, and `swipeAnimatorFrom:to:` and `ANNSwipePopInteraction` play the pop under the finger. Called by: UIKit, the user.
141
143
 
142
144
  ## Modules
143
145
 
@@ -150,7 +152,7 @@ the stores. By area:
150
152
  `ANNArrangementViewController`; `UITabBar+utils`, `ANNBottomTabsAccessoryView`.
151
153
  - **Modals:** `ANNSheetPresenter`, `ANNPopoverPresenter`, `ANNModalSizePresenter`, `ANNModalHostViewComponentView`;
152
154
  `ANNOverlayWindow`.
153
- - **Screen and bar:** `ANNPreviewInteraction`, `ANNScreenInsets`, `ANNScreenRegions`, `ANNNativeScreenContext`,
155
+ - **Screen and bar:** `ANNPreviewInteraction`, `ANNScreenEnvironment`, `ANNScreenRegions`, `ANNNativeScreenContext`,
154
156
  `ANNNativeScreenCalls`, `ANNSearchPresenter`, `ANNSearchResultsViewController`; options `ANNMenuOptions`,
155
157
  `ANNToolbarOptions`, `ANNSheetOptions`, `ANNPopoverOptions`, `ANNBottomTabsAccessoryOptions`.
156
158
  - **React and C++:** `React/Slots/`, `ANNSafeAreaViewComponentView`, the Fabric files of `cpp/`.
@@ -174,8 +176,10 @@ What a module uses of the core:
174
176
  - **The presenter hooks** of `ANNNodePresenter`: `applyOptions:`, `mergeOptions:resolvedOptions:`,
175
177
  `applyDefaultOptionsChange:`, `descendantWillAppear:`, `mergeChildOptions:`, `optionsForParent:`, and the answers to
176
178
  UIKit (status bar, orientations, home indicator, deferred edges).
177
- - **The stores** a module writes on the main queue and JS reads from any thread: `ANNScreenInsets`,
178
- `ANNScreenRegions`, `ANNArrangementState`; and the signals `ANNScreenReadiness`, `ANNSlotContainers`.
179
+ - **The stores** a module writes on the main queue and JS reads from any thread: `ANNScreenEnvironment`, one record
180
+ per screen id (insets and padding, regions, arrangement) under one lock, cleared with one call when the screen goes
181
+ (`removeScreenId:`, only once no node holds the id) and at a reload (`removeAll`); and the signals
182
+ `ANNScreenReadiness`, `ANNSlotContainers`.
179
183
  - **A module's options group** subclasses `ANNOptions` and overrides `initWithDict:`, `mergeOptions:` and `hasValue`.
180
184
 
181
185
  Core code that lives in a module's folder: `ANNSplitViewPresenter` (turns `splitView.*` into calls of
@@ -3,16 +3,17 @@
3
3
 
4
4
  NS_ASSUME_NONNULL_BEGIN
5
5
 
6
- /// Reads and checks a command's layout on the module's queue: the layout read, or nil with the text of the rejection.
6
+ /// Reads and checks a command's layout before its body, in the same task: the layout read, or nil with the text of the
7
+ /// rejection.
7
8
  typedef id _Nullable (^ANNCommandCheck)(NSString *_Nullable *_Nonnull error);
8
9
 
9
- /// The command's own work on the main queue, with the layout its check read (nil without a check). It answers once,
10
- /// now or later; an exception it throws rejects the command, and undoing what it made by then is the body's.
10
+ /// The command's own work, with the layout its check read (nil without a check). It answers once, now or later; an
11
+ /// exception it throws rejects the command, and undoing what it made by then is the body's.
11
12
  typedef void (^ANNCommandBody)(id _Nullable layout, ANNCommandAnswer *answer);
12
13
 
13
- /// The one path of every asynchronous method of `ANNTurboModule`. On the module's queue, at once: the command takes the
14
- /// generation of its JavaScript and its layout is read and checked whole; a failure rejects it there and nothing is
15
- /// queued. Then one task on the main queue per command, in the order they came: the command does nothing when its
14
+ /// The one path of every asynchronous method of `ANNTurboModule`, on the main queue (the module's queue), in one task
15
+ /// per command in the order JavaScript made them: the command takes the generation of its JavaScript and its layout is
16
+ /// read and checked whole, a failure rejecting it before anything is made; then the command does nothing when its
16
17
  /// JavaScript went, rejects when the navigation has nowhere to show screens, and runs its body inside the protection.
17
18
  @interface ANNCommandRunner : NSObject
18
19
 
@@ -27,7 +28,7 @@ typedef void (^ANNCommandBody)(id _Nullable layout, ANNCommandAnswer *answer);
27
28
  check:(nullable ANNCommandCheck)check
28
29
  body:(ANNCommandBody)body;
29
30
 
30
- /// A command without a promise: its body on the main queue, inside the protection; a failure is one log line.
31
+ /// A command without a promise: its body at once, inside the protection; a failure is one log line. Main queue.
31
32
  + (void)runVoid:(NSString *)name what:(NSString *)what body:(dispatch_block_t)body;
32
33
 
33
34
  /// The log line of a command without a promise that failed: `[ApexNavigation] <name>: <text>`.
@@ -1,9 +1,9 @@
1
1
  #import "ANNCommandRunner.h"
2
+ #import "ANNAssert.h"
2
3
  #import "ANNErrorHandler.h"
3
4
  #import "ANNErrorTexts.h"
4
5
  #import "ANNReloadCoordinator.h"
5
6
  #import "ApexNavigation+Internal.h"
6
- #import <React/RCTUtils.h>
7
7
 
8
8
  // Why an exception happened: its message, else its name.
9
9
  static NSString *ANNReasonOf(NSException *exception) {
@@ -27,6 +27,8 @@ static NSString *ANNRejectionOf(NSException *exception, NSString *what) {
27
27
  reject:(RCTPromiseRejectBlock)reject
28
28
  check:(ANNCommandCheck)check
29
29
  body:(ANNCommandBody)body {
30
+ // The module's methods come on the main queue: the check and the body run in this one task.
31
+ ANNAssertMainQueue();
30
32
  NSUInteger generation = ANNReloadCoordinator.generation;
31
33
  id layout = nil;
32
34
  if (check) {
@@ -46,36 +48,28 @@ static NSString *ANNRejectionOf(NSException *exception, NSString *what) {
46
48
  generation:generation
47
49
  resolve:resolve
48
50
  reject:reject];
49
- // At once when the caller is on the main queue already; the module's queue never is.
50
- RCTExecuteOnMainQueue(^{
51
- if (!answer.isCurrent) {
52
- return;
53
- }
54
- if (commandId && !ApexNavigation.mainWindow) {
55
- [answer reject:ANNErrorTexts.nowhereToShow];
56
- return;
57
- }
58
- @try {
59
- body(layout, answer);
60
- } @catch (NSException *exception) {
61
- [answer reject:ANNRejectionOf(exception, what)];
62
- }
63
- });
51
+ if (!answer.isCurrent) {
52
+ return;
53
+ }
54
+ if (commandId && !ApexNavigation.mainWindow) {
55
+ [answer reject:ANNErrorTexts.nowhereToShow];
56
+ return;
57
+ }
58
+ @try {
59
+ body(layout, answer);
60
+ } @catch (NSException *exception) {
61
+ [answer reject:ANNRejectionOf(exception, what)];
62
+ }
64
63
  }
65
64
 
66
65
  // Before the navigation started a command without a promise has nothing to act on: its body finds nothing.
67
66
  + (void)runVoid:(NSString *)name what:(NSString *)what body:(dispatch_block_t)body {
68
- NSUInteger generation = ANNReloadCoordinator.generation;
69
- RCTExecuteOnMainQueue(^{
70
- if (generation != ANNReloadCoordinator.generation) {
71
- return;
72
- }
73
- @try {
74
- body();
75
- } @catch (NSException *exception) {
76
- [self logFailure:name text:[ANNErrorTexts couldNot:what reason:ANNReasonOf(exception)]];
77
- }
78
- });
67
+ ANNAssertMainQueue();
68
+ @try {
69
+ body();
70
+ } @catch (NSException *exception) {
71
+ [self logFailure:name text:[ANNErrorTexts couldNot:what reason:ANNReasonOf(exception)]];
72
+ }
79
73
  }
80
74
 
81
75
  + (void)logFailure:(NSString *)name text:(NSString *)text {
@@ -3,9 +3,9 @@
3
3
 
4
4
  NS_ASSUME_NONNULL_BEGIN
5
5
 
6
- /// One node of a command's layout, as `ANNLayoutReader` read and checked it on the module's queue. Immutable: made off
7
- /// the main queue, read on it by the command. The data stays the JSON JS sent; the accessors give its fields with the
8
- /// kind the contract has, or nothing.
6
+ /// One node of a command's layout, as `ANNLayoutReader` read and checked it before the command's body. Immutable: made
7
+ /// once, read by the command and the steps it runs later. The data stays the JSON JS sent; the accessors give its
8
+ /// fields with the kind the contract has, or nothing.
9
9
  @interface ANNLayoutNode : NSObject
10
10
 
11
11
  /// Made by `ANNLayoutReader` only: the id as JS gave it, the type, the node's `data` (empty when missing) and its
@@ -5,9 +5,9 @@
5
5
  NS_ASSUME_NONNULL_BEGIN
6
6
 
7
7
  /// Reads the layout JSON of a command into `ANNLayoutNode`s and checks it whole, before any view is made. It runs on
8
- /// the module's queue, where the command arrives: a failure rejects the command there with the text of the first error
9
- /// found, and nothing goes to the main queue. It reads only the stores that are safe from any thread (the registered
10
- /// native screens, whether the app shows pairs).
8
+ /// the main queue, in the command's task before its body: a failure rejects the command with the text of the first
9
+ /// error found, and nothing is made. The stores it reads are safe from any thread (the registered native screens,
10
+ /// whether the app shows pairs).
11
11
  ///
12
12
  /// One pass over the tree, depth first, children in order, the same order on both platforms so that the first error
13
13
  /// is the same text. At each node: a known `type` (`''` for a node that is no object or has no string type), an `id`
@@ -71,8 +71,6 @@ static BOOL ANNAppUsesScenes(void) {
71
71
  rootViewFactory.reactHost = host;
72
72
  [ApexNavigation bootstrapWithHost:host];
73
73
  self.window = ApexNavigation.mainWindow;
74
- // The links that come before React content wait for it; the launch link waits for the scene.
75
- [ANNDeepLinkQueue start];
76
74
  if (!ANNAppUsesScenes()) {
77
75
  [self.window makeKeyAndVisible];
78
76
  }
@@ -14,7 +14,8 @@ typedef void (^ANNLaunchLinkCompletion)(NSURL *_Nullable url);
14
14
  */
15
15
  @interface ANNDeepLinkQueue : NSObject
16
16
 
17
- /// Starts the queue as the app launches (`ANNAppDelegate`). An app that never starts it has no launch link.
17
+ /// Starts the queue as the app launches (`+[ApexNavigation bootstrapWithHost:]`, so also under an app delegate of the
18
+ /// app's own). Once: a second call does nothing.
18
19
  + (void)start;
19
20
 
20
21
  /// Hands `url` to `Linking`, or keeps it until React content first appears and no `takeLaunchLink:` waits.
@@ -33,11 +34,11 @@ typedef void (^ANNLaunchLinkCompletion)(NSURL *_Nullable url);
33
34
  ofScene:(UIScene *)scene
34
35
  through:(NS_NOESCAPE dispatch_block_t)forward;
35
36
 
36
- /// Hands the scene's link to `Linking` at once, past the queue: for an app delegate that doesn't take links.
37
- + (void)openURLContext:(UIOpenURLContext *)context ofScene:(UIScene *)scene;
37
+ /// `dispatchURL:` for the scene's link, with its scene and context: for an app delegate that doesn't take links.
38
+ + (void)dispatchURLContext:(UIOpenURLContext *)context ofScene:(UIScene *)scene;
38
39
 
39
- /// `openURLContext:ofScene:` for a web link (`webpageURL`) of the scene; an activity without one does nothing.
40
- + (void)openUserActivity:(NSUserActivity *)activity ofScene:(UIScene *)scene;
40
+ /// `dispatchURLContext:ofScene:` for a web link (`webpageURL`) of the scene; an activity without one does nothing.
41
+ + (void)dispatchUserActivity:(NSUserActivity *)activity ofScene:(UIScene *)scene;
41
42
 
42
43
  /// The app's window scene connected (`+[ApexNavigation attachToWindowScene:]`).
43
44
  + (void)windowSceneDidConnect;