@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
@@ -1,16 +1,8 @@
1
1
  #import "ANNArrangementState.h"
2
2
  #import "ANNArrangementViewController.h"
3
3
 
4
- static NSMutableDictionary<NSString *, NSDictionary<NSString *, id> *> *ANNArrangementStateById;
5
-
6
4
  @implementation ANNArrangementState
7
5
 
8
- + (void)initialize {
9
- if (self == ANNArrangementState.class) {
10
- ANNArrangementStateById = [NSMutableDictionary new];
11
- }
12
- }
13
-
14
6
  + (BOOL)canShowArrangements {
15
7
  #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 270100
16
8
  if (@available(iOS 27.1, *)) {
@@ -20,34 +12,4 @@ static NSMutableDictionary<NSString *, NSDictionary<NSString *, id> *> *ANNArran
20
12
  return NO;
21
13
  }
22
14
 
23
- + (void)setState:(NSDictionary<NSString *, id> *)state
24
- forScreenId:(NSString *)screenId
25
- eventEmitter:(ANNEventEmitter *)eventEmitter {
26
- @synchronized(ANNArrangementStateById) {
27
- if ([ANNArrangementStateById[screenId] isEqualToDictionary:state]) {
28
- return;
29
- }
30
- ANNArrangementStateById[screenId] = state;
31
- }
32
- [eventEmitter sendArrangementChanged:screenId state:state];
33
- }
34
-
35
- + (NSDictionary<NSString *, id> *)stateForScreenId:(NSString *)screenId {
36
- @synchronized(ANNArrangementStateById) {
37
- return ANNArrangementStateById[screenId];
38
- }
39
- }
40
-
41
- + (void)removeScreenId:(NSString *)screenId {
42
- @synchronized(ANNArrangementStateById) {
43
- [ANNArrangementStateById removeObjectForKey:screenId];
44
- }
45
- }
46
-
47
- + (void)removeAll {
48
- @synchronized(ANNArrangementStateById) {
49
- [ANNArrangementStateById removeAllObjects];
50
- }
51
- }
52
-
53
15
  @end
@@ -2,9 +2,10 @@
2
2
 
3
3
  #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 270100
4
4
 
5
- #import "ANNArrangementState.h"
6
5
  #import "ANNComponentViewController.h"
6
+ #import "ANNEventContract.h"
7
7
  #import "ANNExternalViewController.h"
8
+ #import "ANNScreenEnvironment.h"
8
9
  #import "ANNShownScreens.h"
9
10
  #import "ANNUtils.h"
10
11
 
@@ -130,11 +131,12 @@ static BOOL ANNKeepsState(UIViewController *screen) {
130
131
 
131
132
  static NSDictionary<NSString *, id> *ANNStateOf(NSString *placement, NSString *layout, BOOL front,
132
133
  BOOL hidden) {
134
+ const auto &keys = ANNEventContract.ArrangementChanged;
133
135
  return @{
134
- @"placement" : placement,
135
- @"layout" : layout,
136
- @"front" : @(front),
137
- @"hidden" : @(hidden),
136
+ keys.placement : placement,
137
+ keys.layout : layout,
138
+ keys.front : @(front),
139
+ keys.hidden : @(hidden),
138
140
  };
139
141
  }
140
142
 
@@ -296,9 +298,9 @@ static BOOL ANNIsShown(UIViewController *screen, UIArrangementViewState *state,
296
298
  ofScreen:(UIViewController *)screen
297
299
  eventEmitter:(ANNEventEmitter *)eventEmitter {
298
300
  if (ANNKeepsState(screen)) {
299
- [ANNArrangementState setState:state
300
- forScreenId:screen.layoutInfo.componentId
301
- eventEmitter:eventEmitter];
301
+ [ANNScreenEnvironment setArrangement:state
302
+ forScreenId:screen.layoutInfo.componentId
303
+ eventEmitter:eventEmitter];
302
304
  }
303
305
  }
304
306
 
@@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN
25
25
 
26
26
  /// `dismissModal`: the record of `componentId` (its root's id or any id inside, also of a modal closed below or by the
27
27
  /// user), the options merged into its visible screen, the animation from the command's screen, then its state decides.
28
- /// Answers with the root's id.
28
+ /// Answers with the root's id. The last modal over no root rejects `[ANNErrorTexts modalWithoutRoot:]`, as on Android.
29
29
  + (void)dismissModal:(NSString *)componentId
30
30
  options:(nullable NSDictionary *)options
31
31
  answer:(ANNCommandAnswer *)answer;
@@ -233,7 +233,7 @@ static void ANNCollectIds(UIViewController *node, NSMutableSet<NSString *> *ids)
233
233
  limit:contentFirst ? 0 : ANNModalRenderLimit
234
234
  bar:contentFirst ? ANNRenderWaitBarAfterContent : ANNRenderWaitBarWithContent
235
235
  barLimits:contentFirst ? ownPhase : withContent];
236
- wait.mountLimit = ANNModalRenderLimit;
236
+ wait.unseenLimit = ANNModalRenderLimit;
237
237
  wait.protect = ^(dispatch_block_t step) {
238
238
  [ANNModalCoordinator protect:weakModal step:step];
239
239
  };
@@ -277,8 +277,8 @@ static void ANNCollectIds(UIViewController *node, NSMutableSet<NSString *> *ids)
277
277
 
278
278
  // The end steps of a record (its show presented, its dismissal ended, closed by the user) run inside UIKit's
279
279
  // completions and delegate calls, outside the runner's protection, in any state: a failure there is logged in one line,
280
- // rejects what of the record still waits for an answer (its show, a chain step, its dismissals), and its drive stops.
281
- // The gate's `done` ran before the step, as without a failure.
280
+ // answers what of the record still waits for an answer (its show, a chain step, its dismissals:
281
+ // `endFailedOf:showing:exception:`), and its drive stops. The gate's `done` ran before the step, as without a failure.
282
282
  + (void)protectEndOf:(ANNModal *)modal showing:(BOOL)showing step:(dispatch_block_t)step {
283
283
  @try {
284
284
  step();
@@ -288,24 +288,43 @@ static void ANNCollectIds(UIViewController *node, NSMutableSet<NSString *> *ids)
288
288
  : (showing ? @"show a modal" : @"dismiss a modal");
289
289
  NSString *reason = exception.reason.length > 0 ? exception.reason : exception.name;
290
290
  RCTLogWarn(@"[ApexNavigation] %@", [ANNErrorTexts couldNot:what reason:reason]);
291
- [self endFailedOf:modal exception:exception];
291
+ [self endFailedOf:modal showing:showing exception:exception];
292
292
  }
293
293
  }
294
294
 
295
- + (void)endFailedOf:(ANNModal *)modal exception:(NSException *)exception {
295
+ // A failed end step of `modal`: its show rejects. After a failed show the dismissals that wait for it don't fail with
296
+ // it, as on Android: on a modal that shows they run now and resolve once it went (one still `Presenting` shows: UIKit's
297
+ // completion ran); on one that goes another way (a `dismissAllModals`, with the old root) or went already they resolve
298
+ // with its root's id; on one in another transition (a drag, its own dismissal) they wait for that transition's end.
299
+ // A failed dismissal rejects itself and the dismissals behind it.
300
+ + (void)endFailedOf:(ANNModal *)modal showing:(BOOL)showing exception:(NSException *)exception {
296
301
  if (!modal) {
297
302
  return;
298
303
  }
299
304
  [self stopDriving:modal];
300
305
  NSString *show = [NSString stringWithFormat:@"show the screen '%@'", modal.rootId];
301
- NSString *dismiss = [NSString stringWithFormat:@"dismiss the modal '%@'", modal.rootId];
302
306
  [modal.showAnswer reject:[ANNCommandRunner rejectionOf:exception what:show]];
303
- NSString *dismissText = [ANNCommandRunner rejectionOf:exception what:dismiss];
304
- [modal.dismissal.answer reject:dismissText];
305
- NSArray<ANNModalDismissal *> *pending = modal.pending.copy;
306
- [modal.pending removeAllObjects];
307
- for (ANNModalDismissal *waiting in pending) {
308
- [waiting.answer reject:dismissText];
307
+ ANNModalState state = modal.state;
308
+ BOOL goesAnotherWay = (state == ANNModalStateDismissing && modal.batch) ||
309
+ state == ANNModalStateWithOldRoot ||
310
+ state == ANNModalStateClosedBelow || state == ANNModalStateGone;
311
+ if (showing && state == ANNModalStatePresenting) {
312
+ modal.state = ANNModalStateShown;
313
+ }
314
+ if (showing && modal.state == ANNModalStateShown) {
315
+ [self runPendingOf:modal];
316
+ } else if (showing && goesAnotherWay) {
317
+ [modal.dismissal.answer resolve:modal.rootId];
318
+ [self resolvePendingOf:modal];
319
+ } else if (!showing) {
320
+ NSString *dismiss = [NSString stringWithFormat:@"dismiss the modal '%@'", modal.rootId];
321
+ NSString *dismissText = [ANNCommandRunner rejectionOf:exception what:dismiss];
322
+ [modal.dismissal.answer reject:dismissText];
323
+ NSArray<ANNModalDismissal *> *pending = modal.pending.copy;
324
+ [modal.pending removeAllObjects];
325
+ for (ANNModalDismissal *waiting in pending) {
326
+ [waiting.answer reject:dismissText];
327
+ }
309
328
  }
310
329
  // A `setRoot` chain goes on (its own steps are guarded by the root coordinator).
311
330
  void (^chainStep)(BOOL) = modal.chainStep;
@@ -333,7 +352,7 @@ static void ANNCollectIds(UIViewController *node, NSMutableSet<NSString *> *ids)
333
352
  [waiter reject:text];
334
353
  }
335
354
  for (ANNModal *modal in batch.records.copy) {
336
- [self endFailedOf:modal exception:exception];
355
+ [self endFailedOf:modal showing:NO exception:exception];
337
356
  }
338
357
  }
339
358
  }
@@ -407,7 +426,7 @@ static void ANNCollectIds(UIViewController *node, NSMutableSet<NSString *> *ids)
407
426
  ANNNavigationOptions *resolved = [root resolveOptionsWithDefault];
408
427
  ANNModalPresentation *presentation =
409
428
  [[ANNModalPresentation alloc] initWithOptions:resolved animated:modal.animatedOverride];
410
- NSString *problem = [presentation problemPresentingFrom:presenting windowRoot:windowRoot];
429
+ NSString *problem = [presentation fitToPresenting:presenting windowRoot:windowRoot];
411
430
  if (problem) {
412
431
  [self failShowOf:modal reason:problem];
413
432
  done();
@@ -537,7 +556,8 @@ static void ANNCollectIds(UIViewController *node, NSMutableSet<NSString *> *ids)
537
556
  modal.coversUnder = under != nil && under.viewIfLoaded.window == nil;
538
557
  NSArray<UIViewController *> *hidden = modal.coversUnder ? @[ under ] : @[];
539
558
  @try {
540
- // The chain step stays on the record until its events went: a failure there tells the chain (`endFailedOf:`).
559
+ // The chain step stays on the record until its events went: a failure there tells the chain
560
+ // (`endFailedOf:showing:exception:`).
541
561
  void (^chainStep)(BOOL) = modal.chainStep;
542
562
  if (chainStep) {
543
563
  [ANNAppearanceDispatcher endSwitchHiding:hidden showing:@[ root ] events:nil];
@@ -778,6 +798,11 @@ static void ANNCollectIds(UIViewController *node, NSMutableSet<NSString *> *ids)
778
798
  [answer reject:[ANNErrorTexts screenNotShown:componentId]];
779
799
  return;
780
800
  }
801
+ // The last modal over no root (shown before any `setRoot`) stays: nothing would be left to show, as on Android.
802
+ if ([self isLastWithoutRoot:modal]) {
803
+ [answer reject:[ANNErrorTexts modalWithoutRoot:componentId]];
804
+ return;
805
+ }
781
806
  // Step 1: the options, read on the main queue; one that can't be read rejects before anything changes. They merge
782
807
  // into the modal's visible screen as `mergeOptions` would.
783
808
  if (options.count > 0) {
@@ -815,6 +840,22 @@ static void ANNCollectIds(UIViewController *node, NSMutableSet<NSString *> *ids)
815
840
  [self dismiss:modal with:dismissal];
816
841
  }
817
842
 
843
+ // No root in the window (the splash, or nothing yet) and no other modal that shows or comes: `modal` is all a dismissal
844
+ // would take away. One closed below, going with the old root or gone takes nothing away, so it doesn't count.
845
+ + (BOOL)isLastWithoutRoot:(ANNModal *)modal {
846
+ if (modal.state == ANNModalStateClosedBelow || modal.state == ANNModalStateGone ||
847
+ ApexNavigation.mainWindow.rootViewController.isLayoutNode) {
848
+ return NO;
849
+ }
850
+ for (ANNModal *other in ANNModals) {
851
+ if (other != modal && other.state != ANNModalStateClosedBelow &&
852
+ other.state != ANNModalStateWithOldRoot && other.state != ANNModalStateGone) {
853
+ return NO;
854
+ }
855
+ }
856
+ return YES;
857
+ }
858
+
818
859
  // The modal of `node`: the record whose root is the top of `node`'s layout.
819
860
  + (ANNModal *)modalOf:(UIViewController *)node {
820
861
  UIViewController *top = node;
@@ -897,7 +938,7 @@ static void ANNCollectIds(UIViewController *node, NSMutableSet<NSString *> *ids)
897
938
  [ANNErrorTexts couldNot:what reason:exception.reason ?: exception.name]);
898
939
  // The dismissal still open answers, and so do the dismissals waiting behind it (an answer given already
899
940
  // stays as it was).
900
- [self endFailedOf:modal exception:exception];
941
+ [self endFailedOf:modal showing:NO exception:exception];
901
942
  done();
902
943
  }
903
944
  }
@@ -20,7 +20,8 @@ NS_ASSUME_NONNULL_BEGIN
20
20
 
21
21
  /// `modalPresentationStyle`: one to one; unset is UIKit's automatic style; an unknown string full screen.
22
22
  @property(nonatomic, readonly) UIModalPresentationStyle style;
23
- /// `modalTransitionStyle`: `coverVertical` unless one of the others is given.
23
+ /// `modalTransitionStyle`: `coverVertical` unless one of the others is given; `partialCurl` only where UIKit curls
24
+ /// (`fitToPresenting:windowRoot:`).
24
25
  @property(nonatomic, readonly) UIModalTransitionStyle transitionStyle;
25
26
  /// The present is animated: `enter.enabled` is not `false`.
26
27
  @property(nonatomic, readonly) BOOL animated;
@@ -47,10 +48,12 @@ NS_ASSUME_NONNULL_BEGIN
47
48
  animation:(nullable ANNModalAnimationOptions *)animation
48
49
  under:(nullable UIViewController *)under;
49
50
 
50
- /// Why UIKit can't make this show from `presenting` (`partialCurl` only full screen, to and from), as the reason of the
51
- /// rejection; nil when it can. `windowRoot` is the main window's root.
52
- - (nullable NSString *)problemPresentingFrom:(UIViewController *)presenting
53
- windowRoot:(nullable UIViewController *)windowRoot;
51
+ /// Fits the show to `presenting`, before `prepare:…`: `partialCurl` stays only for a full-screen modal over a
52
+ /// controller that fills the screen (`presenting` is `windowRoot`, the main window's root, or a full-screen modal);
53
+ /// otherwise `transitionStyle` becomes `coverVertical`. Returns why UIKit can't make the show (`presenting` was shown
54
+ /// with `partialCurl`), as the reason of the rejection; nil when it can.
55
+ - (nullable NSString *)fitToPresenting:(UIViewController *)presenting
56
+ windowRoot:(nullable UIViewController *)windowRoot;
54
57
 
55
58
  /// Before `presentViewController:`: the style and the transition, the presentation's delegate, the popover kept a
56
59
  /// popover (`adaptive: false`), the sheet, the size, the popover's source on `presentingLayout`, the hold, the
@@ -118,21 +118,21 @@ static NSDictionary<NSString *, NSNumber *> *ANNTransitionStyles(void) {
118
118
  return nil;
119
119
  }
120
120
 
121
- // UIKit takes `partialCurl` only for a full-screen modal over a controller that fills the screen, and a controller
122
- // shown with `partialCurl` presents nothing more: the command rejects before it asks UIKit.
123
- - (NSString *)problemPresentingFrom:(UIViewController *)presenting
124
- windowRoot:(UIViewController *)windowRoot {
121
+ // UIKit curls only a full-screen modal over a controller that fills the screen: elsewhere `partialCurl` is
122
+ // `coverVertical`, so the modal still shows. A controller shown with `partialCurl` presents nothing more: the command
123
+ // rejects before it asks UIKit.
124
+ - (NSString *)fitToPresenting:(UIViewController *)presenting
125
+ windowRoot:(UIViewController *)windowRoot {
125
126
  if (presenting.presentingViewController &&
126
127
  presenting.modalTransitionStyle == UIModalTransitionStylePartialCurl) {
127
- return @"partialCurl needs a full screen modal";
128
+ return @"a modal shown with partialCurl can't show another modal";
128
129
  }
129
- if (_transitionStyle != UIModalTransitionStylePartialCurl) {
130
- return nil;
131
- }
132
- BOOL presentingFills = presenting == windowRoot ||
133
- presenting.modalPresentationStyle == UIModalPresentationFullScreen;
134
- if (_style != UIModalPresentationFullScreen || !presentingFills) {
135
- return @"partialCurl needs a full screen modal";
130
+ if (_transitionStyle == UIModalTransitionStylePartialCurl) {
131
+ BOOL presentingFills = presenting == windowRoot ||
132
+ presenting.modalPresentationStyle == UIModalPresentationFullScreen;
133
+ if (_style != UIModalPresentationFullScreen || !presentingFills) {
134
+ _transitionStyle = UIModalTransitionStyleCoverVertical;
135
+ }
136
136
  }
137
137
  return nil;
138
138
  }
@@ -1,6 +1,7 @@
1
1
  #import "ANNSheetPresenter.h"
2
2
  #import "ANNModalSizePresenter.h"
3
3
  #import "ANNReactView.h"
4
+ #import "ANNUtils.h"
4
5
  #import "UIViewController+LayoutProtocol.h"
5
6
  #import <React/RCTLog.h>
6
7
  #import <objc/runtime.h>
@@ -53,7 +54,7 @@ static NSString *const ANNContentDetent = @"content";
53
54
  + (void)applyOptions:(ANNSheetOptions *)options toSheet:(UISheetPresentationController *)sheet {
54
55
  if (options.detents) {
55
56
  NSMutableArray<UISheetPresentationControllerDetent *> *detents = [NSMutableArray new];
56
- for (id value in options.detents) {
57
+ for (id value in [self sortedDetents:options.detents ofSheet:sheet]) {
57
58
  UISheetPresentationControllerDetent *detent = [self detentFor:value ofSheet:sheet];
58
59
  if (detent) {
59
60
  [detents addObject:detent];
@@ -81,6 +82,85 @@ static NSString *const ANNContentDetent = @"content";
81
82
  }
82
83
  }
83
84
 
85
+ // UIKit wants the detents once each, from the lowest to the highest: it takes the last for the largest and closes the
86
+ // sheet on a drag down from the first. The options may give them in any order and more than once; the first of a
87
+ // repeat stays, and detents of the same height keep their order.
88
+ + (NSArray *)sortedDetents:(NSArray *)values ofSheet:(UISheetPresentationController *)sheet {
89
+ NSMutableArray *detents = [NSMutableArray new];
90
+ NSMutableSet<NSString *> *identifiers = [NSMutableSet new];
91
+ for (id value in values) {
92
+ NSString *identifier = [self identifierFor:value];
93
+ if (identifier && ![identifiers containsObject:identifier]) {
94
+ [identifiers addObject:identifier];
95
+ [detents addObject:value];
96
+ }
97
+ }
98
+ CGFloat maximum = [self maximumDetentHeightOf:sheet];
99
+ return [detents sortedArrayWithOptions:NSSortStable
100
+ usingComparator:^NSComparisonResult(id a, id b) {
101
+ return [self compareHeightOf:a
102
+ with:b
103
+ maximum:maximum
104
+ ofSheet:sheet];
105
+ }];
106
+ }
107
+
108
+ // The content of a sheet sized to it changed its height, and with it maybe its place among the other detents.
109
+ + (void)sortDetentsOfSheet:(UISheetPresentationController *)sheet API_AVAILABLE(ios(16.0)) {
110
+ CGFloat maximum = [self maximumDetentHeightOf:sheet];
111
+ NSArray<UISheetPresentationControllerDetent *> *detents = sheet.detents;
112
+ NSArray<UISheetPresentationControllerDetent *> *sorted = [detents
113
+ sortedArrayWithOptions:NSSortStable
114
+ usingComparator:^NSComparisonResult(UISheetPresentationControllerDetent *a,
115
+ UISheetPresentationControllerDetent *b) {
116
+ return [self compareHeightOf:[self detentForIdentifier:a.identifier]
117
+ with:[self detentForIdentifier:b.identifier]
118
+ maximum:maximum
119
+ ofSheet:sheet];
120
+ }];
121
+ if (![sorted isEqualToArray:detents]) {
122
+ sheet.detents = sorted;
123
+ }
124
+ }
125
+
126
+ + (NSComparisonResult)compareHeightOf:(id)a
127
+ with:(id)b
128
+ maximum:(CGFloat)maximum
129
+ ofSheet:(UISheetPresentationController *)sheet {
130
+ CGFloat heightA = [self heightOf:a maximum:maximum ofSheet:sheet];
131
+ CGFloat heightB = [self heightOf:b maximum:maximum ofSheet:sheet];
132
+ return heightA < heightB ? NSOrderedAscending
133
+ : heightA > heightB ? NSOrderedDescending : NSOrderedSame;
134
+ }
135
+
136
+ // The height a detent of the options stands at, to sort them, as its resolver gives it: 'medium' half of the largest
137
+ // height (UIKit's is about half), 'large' all of it, a height capped at it, 'content' the content's height now, all of
138
+ // it while the content isn't measured.
139
+ + (CGFloat)heightOf:(id)value
140
+ maximum:(CGFloat)maximum
141
+ ofSheet:(UISheetPresentationController *)sheet {
142
+ if ([value isEqual:@"medium"]) {
143
+ return maximum / 2;
144
+ }
145
+ if ([value isKindOfClass:NSNumber.class]) {
146
+ return MIN([value doubleValue], maximum);
147
+ }
148
+ if ([value isEqual:ANNContentDetent]) {
149
+ CGFloat height = [self contentHeightOf:sheet.presentedViewController];
150
+ return height > 0 ? MIN(height, maximum) : maximum;
151
+ }
152
+ return maximum;
153
+ }
154
+
155
+ // About the largest height of a sheet: its container, or the window before it is shown, below the top safe area.
156
+ + (CGFloat)maximumDetentHeightOf:(UISheetPresentationController *)sheet {
157
+ UIView *view = sheet.containerView ?: ANNUtils.mainWindow;
158
+ if (!view) {
159
+ return ANNUtils.mainScreen.bounds.size.height;
160
+ }
161
+ return view.bounds.size.height - view.safeAreaInsets.top;
162
+ }
163
+
84
164
  + (UISheetPresentationControllerDetent *)detentFor:(id)value
85
165
  ofSheet:(UISheetPresentationController *)sheet {
86
166
  if ([value isEqual:@"medium"]) {
@@ -180,6 +260,7 @@ static NSString *const ANNContentDetent = @"content";
180
260
  }
181
261
  height = newHeight;
182
262
  [strongSheet animateChanges:^{
263
+ [self sortDetentsOfSheet:strongSheet];
183
264
  [strongSheet invalidateDetents];
184
265
  }];
185
266
  }
@@ -201,6 +282,7 @@ static NSString *const ANNContentDetent = @"content";
201
282
  // The new screen's content mounts may come later: its mounts resolve the detents again too.
202
283
  [self followContentOfSheet:sheet when:YES];
203
284
  [sheet animateChanges:^{
285
+ [self sortDetentsOfSheet:sheet];
204
286
  [sheet invalidateDetents];
205
287
  }];
206
288
  }
@@ -179,7 +179,7 @@ static NSMutableArray<ANNOverlay *> *ANNOverlays;
179
179
  limit:ANNOverlayRenderLimit
180
180
  bar:ANNRenderWaitBarWithContent
181
181
  barLimits:withContent];
182
- wait.mountLimit = ANNOverlayRenderLimit;
182
+ wait.unseenLimit = ANNOverlayRenderLimit;
183
183
  wait.protect = ^(dispatch_block_t step) {
184
184
  [ANNOverlayCoordinator protectWaitOf:weakOverlay step:step];
185
185
  };
@@ -238,13 +238,7 @@ static NSMutableArray<ANNOverlay *> *ANNOverlays;
238
238
  [self dismiss:shown answer:nil];
239
239
  }
240
240
  }
241
- UIWindow *mainWindow = ApexNavigation.mainWindow;
242
- UIWindowScene *scene = mainWindow.windowScene;
243
- // `initWithFrame:` is deprecated from iOS 26 on and warns only with a deployment target from 26: a window
244
- // without a scene is made so, and joins the scene as the main window gets it.
245
- ANNOverlayWindow *window =
246
- scene ? [[ANNOverlayWindow alloc] initWithWindowScene:scene]
247
- : [[ANNOverlayWindow alloc] initWithFrame:ANNUtils.mainScreen.bounds];
241
+ ANNOverlayWindow *window = [ANNUtils makeWindowOfClass:ANNOverlayWindow.class];
248
242
  window.windowLevel = UIWindowLevelNormal;
249
243
  window.backgroundColor = UIColor.clearColor;
250
244
  window.previousWindow = [self keyWindow];
@@ -69,7 +69,10 @@ typedef NS_ENUM(NSInteger, ANNRootShowState) {
69
69
  // The nodes whose appearance the transition reports itself (`driveAppearanceOf:`), while `driving`.
70
70
  @property(nonatomic, copy) NSArray<UIViewController *> *driven;
71
71
  @property(nonatomic) BOOL driving;
72
+ // The snapshot of the window as it was: it dissolves over the new root (`dissolves`), plays its `exit` (`custom`), or
73
+ // only covers the old root's modals while they go, and leaves as the new root is the window's.
72
74
  @property(nonatomic, strong, nullable) UIView *snapshot;
75
+ @property(nonatomic) BOOL dissolves;
73
76
  // The root is the window's root: the old root's modals went before it (`startTransitionOf:done:`).
74
77
  @property(nonatomic) BOOL installed;
75
78
  // The root's view waits in the window under the current root (`park:`).
@@ -80,6 +83,10 @@ typedef NS_ENUM(NSInteger, ANNRootShowState) {
80
83
  @property(nonatomic, strong, nullable) ANNFrameDriver *driver;
81
84
  @property(nonatomic, copy, nullable) NSArray<ANNViewTracks *> *tracks;
82
85
  @property(nonatomic) BOOL animating;
86
+ // The new root's view takes no touches while it animates, and whether it took them before: Core Animation draws it
87
+ // elsewhere than where it is (the view itself stays in place), so a tap on the old screen would reach it.
88
+ @property(nonatomic, weak, nullable) UIView *untouchableRoot;
89
+ @property(nonatomic) BOOL rootTouchesBefore;
83
90
  @property(nonatomic) BOOL layersShown;
84
91
  @end
85
92
 
@@ -293,7 +300,7 @@ static __weak ANNRootShow *ANNAnimatingShow;
293
300
  barLimits:contentFirst ? ownPhase : withContent];
294
301
  // A screen the user won't see at once (an unselected tab's) never holds the root longer than the limit, also with
295
302
  // `waitForRender: true`.
296
- wait.mountLimit = ANNRootRenderLimit;
303
+ wait.unseenLimit = ANNRootRenderLimit;
297
304
  wait.protect = ^(dispatch_block_t step) {
298
305
  [ANNRootCoordinator protect:weakShow step:step];
299
306
  };
@@ -415,9 +422,14 @@ static __weak ANNRootShow *ANNAnimatingShow;
415
422
  BOOL seen = !window.hidden && scene != nil &&
416
423
  scene.activationState != UISceneActivationStateBackground;
417
424
  BOOL dissolves = !overSplash && !enterDisabled && !custom && seen;
425
+ show.dissolves = dissolves;
418
426
  show.custom = custom && seen;
419
- UIView *snapshot =
420
- dissolves || show.custom ? [window snapshotViewAfterScreenUpdates:NO] : nil;
427
+ // UIKit draws the dismissal of the old root's modals, without animation too (a sheet's dim goes a frame before
428
+ // its card): with nothing to dissolve, the snapshot covers them until the new root is in place.
429
+ BOOL covers = seen && old.presentedViewController != nil;
430
+ UIView *snapshot = dissolves || show.custom || covers
431
+ ? [window snapshotViewAfterScreenUpdates:NO]
432
+ : nil;
421
433
 
422
434
  show.state = ANNRootShowStateTransition;
423
435
  // It shows from here: a stack in it counts as on screen.
@@ -480,7 +492,8 @@ static __weak ANNRootShow *ANNAnimatingShow;
480
492
  [self endTransitionOf:show];
481
493
  return;
482
494
  }
483
- if (!snapshot) {
495
+ // A snapshot that only covered the old root's modals leaves in this turn, with the new root in place under it.
496
+ if (!snapshot || !show.dissolves) {
484
497
  [self endTransitionOf:show];
485
498
  return;
486
499
  }
@@ -524,20 +537,43 @@ static __weak ANNRootShow *ANNAnimatingShow;
524
537
  NSMutableArray<ANNViewTracks *> *tracks = [NSMutableArray new];
525
538
  ANNViewAnimationOptions *enter = [ANNAnimationRules playingSide:animation.enter];
526
539
  ANNViewAnimationOptions *exit = [ANNAnimationRules playingSide:animation.exit];
527
- if (enter && rootView) {
528
- [tracks addObject:[[ANNViewTracks alloc] initWithView:rootView
529
- side:enter
530
- alphaBefore:rootView.alpha]];
531
- }
532
- if (exit && snapshot) {
533
- [tracks addObject:[[ANNViewTracks alloc] initWithView:snapshot
534
- side:exit
535
- alphaBefore:snapshot.alpha]];
536
- }
537
540
  NSTimeInterval length =
538
541
  MAX([ANNAnimationRules lengthOfSide:enter], [ANNAnimationRules lengthOfSide:exit]);
542
+ if (UIAccessibilityIsReduceMotionEnabled() && length > 0) {
543
+ // With the system's Reduce Motion on, nothing moves: the new root fades in over the snapshot in the same
544
+ // length, or the snapshot fades out without a new root's view.
545
+ if (rootView) {
546
+ [tracks addObject:[[ANNViewTracks alloc] initWithView:rootView
547
+ fadeFrom:0
548
+ to:rootView.alpha
549
+ duration:length
550
+ alphaBefore:rootView.alpha]];
551
+ } else if (snapshot) {
552
+ [tracks addObject:[[ANNViewTracks alloc] initWithView:snapshot
553
+ fadeFrom:snapshot.alpha
554
+ to:0
555
+ duration:length
556
+ alphaBefore:snapshot.alpha]];
557
+ }
558
+ } else {
559
+ if (enter && rootView) {
560
+ [tracks addObject:[[ANNViewTracks alloc] initWithView:rootView
561
+ side:enter
562
+ alphaBefore:rootView.alpha]];
563
+ }
564
+ if (exit && snapshot) {
565
+ [tracks addObject:[[ANNViewTracks alloc] initWithView:snapshot
566
+ side:exit
567
+ alphaBefore:snapshot.alpha]];
568
+ }
569
+ }
539
570
  show.tracks = tracks;
540
571
  show.animating = YES;
572
+ if (rootView) {
573
+ show.untouchableRoot = rootView;
574
+ show.rootTouchesBefore = rootView.userInteractionEnabled;
575
+ rootView.userInteractionEnabled = NO;
576
+ }
541
577
  ANNAnimatingShow = show;
542
578
  show.driver = [[ANNFrameDriver alloc] initWithClients:tracks length:length];
543
579
  // The layers' state from here on: the chain may start and a newer `setRoot` stops it.
@@ -574,8 +610,8 @@ static __weak ANNRootShow *ANNAnimatingShow;
574
610
  [self finishLayersOf:show];
575
611
  }
576
612
 
577
- // The animation stops at its end state (its end, a newer `setRoot`, a reload, a failure): the views get back what they
578
- // had and the snapshot goes.
613
+ // The animation stops (its end, a newer `setRoot`, a reload, a failure): its animations go, the views get back what
614
+ // they had and the snapshot goes.
579
615
  + (void)stopAnimationOf:(ANNRootShow *)show {
580
616
  if (!show.animating) {
581
617
  return;
@@ -583,13 +619,16 @@ static __weak ANNRootShow *ANNAnimatingShow;
583
619
  show.animating = NO;
584
620
  [show.driver cancel];
585
621
  show.driver = nil;
622
+ show.untouchableRoot.userInteractionEnabled = show.rootTouchesBefore;
623
+ show.untouchableRoot = nil;
586
624
  for (ANNViewTracks *tracks in show.tracks) {
587
625
  [tracks restore];
588
626
  }
589
627
  show.tracks = nil;
590
- // UIKit works out the safe area of the window's root view from where the view is drawn: moved away from the top
591
- // edge by `enter` (from the bottom, scaled down) it has no top inset, and putting the transform back doesn't make
592
- // UIKit work it out again. A layout now gives the root, its bars and its screens the window's safe area back.
628
+ // UIKit works out the safe area of the window's root view from where the view is: moved away from the top edge by
629
+ // a transform it has no top inset, and putting the transform back doesn't make UIKit work it out again. `enter`
630
+ // moves only what Core Animation draws now; the layout stays, so the root, its bars and its screens end with the
631
+ // window's safe area whatever moved them.
593
632
  UIView *rootView = show.root.viewIfLoaded;
594
633
  [rootView setNeedsLayout];
595
634
  [rootView layoutIfNeeded];
@@ -7,9 +7,11 @@ NS_ASSUME_NONNULL_BEGIN
7
7
  /// either at once. The status bar follows the Info.plist keys `UIStatusBarStyle` and `UIStatusBarHidden`. Main queue.
8
8
  @interface ANNSplashViewController : UIViewController
9
9
 
10
- /// The copy of the launch screen: the initial view controller of `UILaunchStoryboardName` as a child (a storyboard
11
- /// that doesn't load: the first view of the nib of that name), else the legacy launch images, full screen. Nil when the
12
- /// app has none of these: the window then has no root view controller until the first root.
10
+ /// The copy of the launch screen. When iOS builds it from the Info.plist (`UILaunchScreen`, or the default of
11
+ /// `UILaunchScreens`), the same color, image and bars as plain views; else the initial view controller of
12
+ /// `UILaunchStoryboardName` as a child (a storyboard that doesn't load: the first view of the nib of that name), else
13
+ /// the legacy launch images, full screen. Nil when the app has none of these: the window then has no root view
14
+ /// controller until the first root.
13
15
  + (nullable instancetype)launchScreenCopyWithBounds:(CGRect)bounds;
14
16
 
15
17
  /// The blank screen after a reload: clear when the default options give the window a color (`window.backgroundColor`),