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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (581) hide show
  1. package/ApexNavigation.podspec +2 -1
  2. package/CHANGELOG.md +132 -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/ArrangementDefinition.kt +9 -3
  67. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementPlanner.kt +20 -15
  68. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/SecondaryScreenPresenter.kt +13 -5
  69. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/AppliedTabCalls.kt +49 -0
  70. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsCollapseBehavior.kt +5 -3
  71. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsController.kt +108 -34
  72. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsPresenter.kt +25 -24
  73. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowGeometry.kt +22 -0
  74. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabItems.kt +3 -3
  75. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabsRoom.kt +0 -5
  76. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentPresenter.kt +28 -7
  77. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentViewController.kt +12 -9
  78. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ContentReadiness.kt +2 -2
  79. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/RenderWait.kt +27 -7
  80. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenFrame.kt +1 -1
  81. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenReadiness.kt +103 -56
  82. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenSafeArea.kt +29 -11
  83. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/externalcomponent/ExternalComponentViewController.kt +2 -6
  84. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalAnimations.kt +22 -24
  85. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalCoordinator.kt +109 -21
  86. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalRecord.kt +21 -6
  87. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalSheet.kt +476 -73
  88. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalViews.kt +57 -25
  89. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetBack.kt +42 -0
  90. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetStops.kt +83 -0
  91. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackCheck.kt +50 -0
  92. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackState.kt +49 -14
  93. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/Navigator.kt +71 -12
  94. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/RootCoordinator.kt +37 -11
  95. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/overlay/OverlayCoordinator.kt +10 -8
  96. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/Capabilities.kt +11 -4
  97. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ContainerBackground.kt +3 -3
  98. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ParentController.kt +6 -6
  99. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuController.kt +42 -9
  100. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuMotion.kt +19 -8
  101. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuPresenter.kt +16 -7
  102. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuRules.kt +43 -4
  103. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitPanes.kt +23 -0
  104. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitViewController.kt +77 -17
  105. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/BackPreview.kt +315 -0
  106. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/PreparedFrame.kt +3 -3
  107. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackCommands.kt +30 -20
  108. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackController.kt +216 -18
  109. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackDisplay.kt +26 -1
  110. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackQueue.kt +149 -41
  111. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackTransitions.kt +26 -8
  112. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackViews.kt +115 -6
  113. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabMotion.kt +142 -0
  114. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabPresenter.kt +222 -48
  115. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/ScreenSearch.kt +3 -5
  116. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/StackSearchPresenter.kt +30 -34
  117. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarComponents.kt +5 -51
  118. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarRowTransition.kt +3 -2
  119. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/ButtonPlaces.kt +11 -5
  120. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/MenuChecks.kt +13 -56
  121. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarPresenter.kt +219 -54
  122. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarVisibility.kt +9 -2
  123. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ScrollEventListener.kt +6 -9
  124. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ViewController.kt +75 -21
  125. package/android/src/main/java/dev/apexnative/navigation/views/animations/AnimationLayer.kt +73 -0
  126. package/android/src/main/java/dev/apexnative/navigation/views/animations/Curves.kt +29 -11
  127. package/android/src/main/java/dev/apexnative/navigation/views/animations/ValueInterpolation.kt +14 -0
  128. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabs.kt +9 -7
  129. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabsLayout.kt +61 -2
  130. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomBottomTabItemView.kt +0 -5
  131. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomTabRow.kt +72 -10
  132. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStep.kt +31 -0
  133. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementTransitions.kt +143 -135
  134. package/android/src/main/java/dev/apexnative/navigation/views/element/TargetsWait.kt +13 -5
  135. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionLayer.kt +37 -112
  136. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionTargets.kt +9 -6
  137. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionViews.kt +100 -0
  138. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ElementPictures.kt +112 -4
  139. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/FlightGeometry.kt +346 -36
  140. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMorph.kt +199 -0
  141. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/SharedAnimatorFactory.kt +56 -41
  142. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextMorph.kt +176 -0
  143. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewMorph.kt +108 -0
  144. package/android/src/main/java/dev/apexnative/navigation/views/sidemenu/SideMenuView.kt +12 -3
  145. package/android/src/main/java/dev/apexnative/navigation/views/stack/ScreenEdge.kt +45 -0
  146. package/android/src/main/java/dev/apexnative/navigation/views/stack/StackLayout.kt +140 -1
  147. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/Fab.kt +14 -10
  148. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabCopy.kt +85 -0
  149. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabMenu.kt +13 -0
  150. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TitleBar.kt +5 -17
  151. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TopBar.kt +73 -34
  152. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonComponentCell.kt +6 -6
  153. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonView.kt +113 -0
  154. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarMenu.kt +219 -0
  155. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonBar.kt +125 -178
  156. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonMenus.kt +34 -64
  157. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonRow.kt +216 -0
  158. package/android/src/main/jni/ANNContentHeights.cpp +82 -0
  159. package/android/src/main/res/drawable/apex_navigation_ic_arrow_right.xml +14 -0
  160. package/android/src/main/res/layout/apex_navigation_menu_header.xml +19 -0
  161. package/android/src/main/res/layout/apex_navigation_menu_item.xml +68 -0
  162. package/android/src/main/res/values/styles.xml +1 -1
  163. package/android/src/main/res/values-night/styles.xml +1 -1
  164. package/cli/app.js +1 -1
  165. package/cli/doctor/checks/app.js +77 -14
  166. package/cli/doctor/checks/splash.js +4 -22
  167. package/cli/migrate/native.js +18 -0
  168. package/cli/project.js +10 -2
  169. package/cli/setup/index.js +18 -0
  170. package/cli/setup/source.js +2 -1
  171. package/cli/setup/steps/appDelegate.js +66 -11
  172. package/cli/setup/steps/mainApplication.js +134 -19
  173. package/cli/setup/steps/metro.js +46 -0
  174. package/cli/setup/steps/sceneDelegate.js +108 -0
  175. package/cli/splash/index.js +3 -1
  176. package/docs-md/architecture/native-screens.md +4 -0
  177. package/docs-md/architecture/theme-and-context.md +131 -12
  178. package/docs-md/architecture/transitions.md +58 -12
  179. package/docs-md/containers/arrangement.md +17 -1
  180. package/docs-md/containers/modals.md +8 -4
  181. package/docs-md/containers/overlays.md +3 -1
  182. package/docs-md/containers/side-menu.md +19 -2
  183. package/docs-md/containers/tabs.md +5 -1
  184. package/docs-md/flows/bottom-sheets.md +4 -2
  185. package/docs-md/flows/forms-in-a-modal.md +1 -1
  186. package/docs-md/fundamentals/screens-and-props.md +9 -1
  187. package/docs-md/fundamentals/starting-the-app.md +1 -1
  188. package/docs-md/guides/cli.md +4 -3
  189. package/docs-md/guides/deep-links.md +15 -33
  190. package/docs-md/help/glossary.md +4 -4
  191. package/docs-md/help/troubleshooting.md +44 -6
  192. package/docs-md/index.json +61 -1
  193. package/docs-md/migration/from-expo-router.md +1 -1
  194. package/docs-md/migration/from-react-native-navigation.md +9 -3
  195. package/docs-md/migration/from-react-navigation.md +2 -2
  196. package/docs-md/screen-ui/back-and-gestures.md +46 -2
  197. package/docs-md/screen-ui/bar-buttons.md +5 -5
  198. package/docs-md/screen-ui/search.md +1 -1
  199. package/docs-md/screen-ui/system-ui.md +17 -12
  200. package/docs-md/screen-ui/toolbar-and-fab.md +4 -2
  201. package/docs-md/screen-ui/top-bar.md +8 -4
  202. package/docs-md/start/installation.md +21 -3
  203. package/ios/Animations/ANNFrameDriver.h +55 -15
  204. package/ios/Animations/ANNFrameDriver.mm +216 -60
  205. package/ios/Animations/ANNTransitionAnimator.h +26 -5
  206. package/ios/Animations/ANNTransitionAnimator.mm +61 -13
  207. package/ios/Animations/ANNTransitionPlan.h +2 -2
  208. package/ios/Animations/ANNTransitionPlan.mm +10 -0
  209. package/ios/Animations/ANNTransitionWait.mm +6 -7
  210. package/ios/Animations/Elements/ANNElementFinder.h +57 -0
  211. package/ios/Animations/Elements/ANNElementFinder.mm +174 -2
  212. package/ios/Animations/Elements/ANNElementTransition.h +10 -8
  213. package/ios/Animations/Elements/ANNElementTransition.mm +19 -21
  214. package/ios/Animations/Elements/ANNSharedElementFlight.h +16 -11
  215. package/ios/Animations/Elements/ANNSharedElementFlight.mm +308 -69
  216. package/ios/Animations/Interpolators/ANNInterpolate.h +2 -30
  217. package/ios/Animations/Interpolators/ANNTransformParts.h +48 -0
  218. package/ios/Animations/Interpolators/ANNTransformParts.mm +507 -0
  219. package/ios/Animations/Interpolators/ANNViewTracks.h +9 -6
  220. package/ios/Animations/Interpolators/ANNViewTracks.mm +100 -30
  221. package/ios/CLAUDE.md +60 -24
  222. package/ios/CORE.md +44 -34
  223. package/ios/Contract/ANNCommandAnswer.h +13 -5
  224. package/ios/Contract/ANNCommandAnswer.mm +40 -32
  225. package/ios/Contract/ANNCommandContract.h +15 -0
  226. package/ios/Contract/ANNCommandContract.mm +78 -0
  227. package/ios/Contract/ANNCommandRunner.h +10 -9
  228. package/ios/Contract/ANNCommandRunner.mm +22 -28
  229. package/ios/Contract/ANNErrorTexts.h +6 -2
  230. package/ios/Contract/ANNErrorTexts.mm +18 -10
  231. package/ios/Contract/ANNLayoutNode.h +3 -3
  232. package/ios/Contract/ANNLayoutReader.h +3 -3
  233. package/ios/Core/ANNAppDelegate.mm +0 -2
  234. package/ios/Core/ANNAppearanceDispatcher.h +5 -4
  235. package/ios/Core/ANNAppearanceDispatcher.mm +12 -1
  236. package/ios/Core/ANNDeepLinkQueue.h +22 -2
  237. package/ios/Core/ANNDeepLinkQueue.mm +121 -14
  238. package/ios/Core/ANNErrorHandler.h +9 -4
  239. package/ios/Core/ANNErrorHandler.mm +20 -2
  240. package/ios/Core/ANNEventContract.h +246 -0
  241. package/ios/Core/ANNEventContract.mm +225 -0
  242. package/ios/Core/ANNEventEmitter.h +6 -2
  243. package/ios/Core/ANNEventEmitter.mm +117 -80
  244. package/ios/Core/ANNHinge.h +6 -0
  245. package/ios/Core/ANNHinge.mm +15 -4
  246. package/ios/Core/ANNJavaScriptCalls.h +33 -0
  247. package/ios/Core/ANNJavaScriptCalls.mm +52 -0
  248. package/ios/Core/ANNLayoutProtocol.h +5 -5
  249. package/ios/Core/ANNNavigationState.h +7 -5
  250. package/ios/Core/ANNNavigationState.mm +8 -7
  251. package/ios/Core/ANNNodeHelper.h +32 -12
  252. package/ios/Core/ANNNodeHelper.mm +100 -3
  253. package/ios/Core/ANNParking.h +5 -4
  254. package/ios/Core/ANNReloadCoordinator.mm +5 -12
  255. package/ios/Core/ANNRenderWait.h +20 -6
  256. package/ios/Core/ANNRenderWait.mm +143 -56
  257. package/ios/Core/ANNSceneDelegate.mm +25 -15
  258. package/ios/Core/ANNSystemUI.h +3 -2
  259. package/ios/Core/ANNSystemUI.mm +7 -0
  260. package/ios/Core/ANNUtils.h +7 -0
  261. package/ios/Core/ANNUtils.mm +10 -0
  262. package/ios/Core/ApexNavigation+Internal.h +1 -1
  263. package/ios/Core/ApexNavigation.mm +7 -6
  264. package/ios/Core/UIViewController+LayoutProtocol.h +9 -2
  265. package/ios/Core/UIViewController+LayoutProtocol.mm +8 -0
  266. package/ios/Layouts/Arrangement/ANNArrangementState.h +2 -17
  267. package/ios/Layouts/Arrangement/ANNArrangementState.mm +0 -38
  268. package/ios/Layouts/Arrangement/ANNArrangementViewController.mm +195 -21
  269. package/ios/Layouts/Modal/ANNModalCoordinator.h +1 -1
  270. package/ios/Layouts/Modal/ANNModalCoordinator.mm +57 -16
  271. package/ios/Layouts/Modal/ANNModalPresentation.h +8 -5
  272. package/ios/Layouts/Modal/ANNModalPresentation.mm +12 -12
  273. package/ios/Layouts/Modal/ANNSheetPresenter.mm +83 -1
  274. package/ios/Layouts/Overlay/ANNOverlayCoordinator.mm +2 -8
  275. package/ios/Layouts/Root/ANNRootCoordinator.mm +58 -19
  276. package/ios/Layouts/Root/ANNSplashViewController.h +5 -3
  277. package/ios/Layouts/Root/ANNSplashViewController.mm +147 -0
  278. package/ios/Layouts/Screen/ANNComponentPresenter.h +11 -3
  279. package/ios/Layouts/Screen/ANNComponentPresenter.mm +34 -6
  280. package/ios/Layouts/Screen/ANNComponentViewController.h +15 -13
  281. package/ios/Layouts/Screen/ANNComponentViewController.mm +130 -75
  282. package/ios/Layouts/Screen/ANNNativeScreenContext.mm +7 -5
  283. package/ios/Layouts/Screen/ANNPreviewInteraction.h +7 -4
  284. package/ios/Layouts/Screen/ANNPreviewInteraction.mm +72 -10
  285. package/ios/Layouts/Screen/ANNScreenEnvironment.h +63 -0
  286. package/ios/Layouts/Screen/ANNScreenEnvironment.mm +181 -0
  287. package/ios/Layouts/Screen/ANNScreenPlace.h +53 -0
  288. package/ios/Layouts/Screen/ANNScreenPlace.mm +205 -0
  289. package/ios/Layouts/Screen/ANNScreenRegions.h +3 -18
  290. package/ios/Layouts/Screen/ANNScreenRegions.mm +9 -44
  291. package/ios/Layouts/Screen/ANNScreenSafeArea.h +4 -9
  292. package/ios/Layouts/Screen/ANNScreenSafeArea.mm +14 -16
  293. package/ios/Layouts/Screen/ANNScreenSettling.h +34 -0
  294. package/ios/Layouts/Screen/ANNScreenSettling.mm +171 -0
  295. package/ios/Layouts/SideMenu/ANNSideMenuTypes.h +8 -0
  296. package/ios/Layouts/SideMenu/ANNSideMenuViewController.mm +83 -14
  297. package/ios/Layouts/SplitView/ANNSplitViewCommands.h +3 -2
  298. package/ios/Layouts/SplitView/ANNSplitViewCommands.mm +105 -39
  299. package/ios/Layouts/SplitView/ANNSplitViewController.mm +7 -8
  300. package/ios/Layouts/Stack/ANNPreviewPush.h +7 -6
  301. package/ios/Layouts/Stack/ANNPreviewPush.mm +142 -27
  302. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.h +11 -2
  303. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.mm +14 -7
  304. package/ios/Layouts/Stack/ANNStackCommands.mm +1 -0
  305. package/ios/Layouts/Stack/ANNStackController.h +8 -0
  306. package/ios/Layouts/Stack/ANNStackController.mm +184 -16
  307. package/ios/Layouts/Stack/ANNStackQueue.h +5 -2
  308. package/ios/Layouts/Stack/ANNStackQueue.mm +56 -43
  309. package/ios/Layouts/Stack/ANNSwipePopInteraction.h +26 -0
  310. package/ios/Layouts/Stack/ANNSwipePopInteraction.mm +185 -0
  311. package/ios/Layouts/Stack/InteractivePopGestureDelegate.mm +28 -4
  312. package/ios/Layouts/Stack/UINavigationController+ANNCommands.h +4 -2
  313. package/ios/Layouts/Stack/UINavigationController+ANNCommands.mm +2 -3
  314. package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.h +4 -0
  315. package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.mm +11 -0
  316. package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.h +12 -1
  317. package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.mm +23 -0
  318. package/ios/Layouts/Tabs/ANNBottomTabsController.h +3 -0
  319. package/ios/Layouts/Tabs/ANNBottomTabsController.mm +237 -57
  320. package/ios/Layouts/Tabs/ANNBottomTabsCustomRow.mm +8 -3
  321. package/ios/Layouts/Tabs/ANNBottomTabsPresenter.h +6 -2
  322. package/ios/Layouts/Tabs/ANNBottomTabsPresenter.mm +232 -43
  323. package/ios/Layouts/Tabs/ANNTabsDesign.h +6 -5
  324. package/ios/Layouts/Tabs/ANNTabsDesign.mm +9 -1
  325. package/ios/Layouts/Tabs/UITabBar+utils.h +5 -5
  326. package/ios/Layouts/Tabs/UITabBar+utils.mm +32 -13
  327. package/ios/Options/ANNAnimationOptions.h +2 -1
  328. package/ios/Options/ANNAnimationOptions.mm +1 -1
  329. package/ios/Options/ANNBottomTabsOptions.h +2 -0
  330. package/ios/Options/ANNBottomTabsOptions.mm +1 -0
  331. package/ios/Options/ANNOptions.h +25 -0
  332. package/ios/Options/ANNOptions.mm +157 -1
  333. package/ios/Options/ANNOptionsCache.h +7 -6
  334. package/ios/Options/ANNOptionsReader.mm +108 -0
  335. package/ios/Options/ANNSearchBarOptions.h +4 -3
  336. package/ios/Options/ANNSheetOptions.h +4 -1
  337. package/ios/Options/ANNSideMenuOptions.h +2 -0
  338. package/ios/Options/ANNSideMenuOptions.mm +2 -0
  339. package/ios/Options/ANNStackPopAnimationOptions.h +13 -0
  340. package/ios/Options/ANNStackPopAnimationOptions.mm +11 -0
  341. package/ios/Options/ANNUserChoice.h +57 -0
  342. package/ios/Options/ANNUserChoice.mm +44 -0
  343. package/ios/Options/Params/ANNImageSource.h +61 -0
  344. package/ios/Options/Params/ANNImageSource.mm +101 -0
  345. package/ios/Options/Params/ANNOptionImages.h +37 -0
  346. package/ios/Options/Params/ANNOptionImages.mm +284 -0
  347. package/ios/Options/Params/ANNParam.h +15 -0
  348. package/ios/Options/Params/ANNParam.mm +61 -0
  349. package/ios/Options/Params/Color.h +3 -0
  350. package/ios/Options/Params/Color.mm +21 -0
  351. package/ios/Options/Params/ColorParser.h +4 -3
  352. package/ios/Options/Params/ColorParser.mm +22 -4
  353. package/ios/Options/Params/Image.h +15 -2
  354. package/ios/Options/Params/Image.mm +35 -2
  355. package/ios/Options/Params/ImageParser.h +5 -5
  356. package/ios/Options/Params/ImageParser.mm +28 -46
  357. package/ios/Public/ApexNavigation/ANNSceneDelegate.h +3 -0
  358. package/ios/Public/ApexNavigation/ApexNavigation.h +1 -1
  359. package/ios/RECIPES.md +13 -6
  360. package/ios/React/ANNReactView.mm +6 -25
  361. package/ios/React/ANNSafeAreaViewComponentView.mm +28 -17
  362. package/ios/React/ANNSurfaceHostingView.h +14 -0
  363. package/ios/React/ANNSurfaceHostingView.mm +144 -1
  364. package/ios/React/Slots/ANNSlotComponentView.mm +24 -17
  365. package/ios/React/Slots/ANNSlotContainers.h +14 -6
  366. package/ios/React/Slots/ANNSlotContainers.mm +75 -2
  367. package/ios/React/Slots/ANNSlotHost.mm +1 -3
  368. package/ios/React/Slots/ANNSlotScreenView.mm +8 -2
  369. package/ios/TopBar/ANNBackButtonPresenter.mm +6 -5
  370. package/ios/TopBar/ANNBarAppearance.h +2 -1
  371. package/ios/TopBar/ANNBarAppearance.mm +111 -30
  372. package/ios/TopBar/ANNBarBackgroundComponent.mm +16 -0
  373. package/ios/TopBar/ANNBarButtonComponentView.h +4 -4
  374. package/ios/TopBar/ANNBarButtonComponentView.mm +1 -1
  375. package/ios/TopBar/ANNBarButtons.h +14 -8
  376. package/ios/TopBar/ANNBarButtons.mm +397 -80
  377. package/ios/TopBar/ANNIconButtonImage.h +1 -0
  378. package/ios/TopBar/ANNIconButtonImage.mm +34 -1
  379. package/ios/TopBar/ANNLargeTitlePresenter.h +13 -0
  380. package/ios/TopBar/ANNLargeTitlePresenter.mm +50 -7
  381. package/ios/TopBar/ANNMainList.h +3 -0
  382. package/ios/TopBar/ANNMainList.mm +4 -0
  383. package/ios/TopBar/ANNScrollEdgeEffects.h +22 -6
  384. package/ios/TopBar/ANNScrollEdgeEffects.mm +123 -16
  385. package/ios/TopBar/ANNSearchPresenter.mm +172 -21
  386. package/ios/TopBar/ANNSearchResultsViewController.mm +29 -6
  387. package/ios/TopBar/ANNTopBarPresenter.h +8 -2
  388. package/ios/TopBar/ANNTopBarPresenter.mm +155 -33
  389. package/ios/TurboModules/ANNTurboEventEmitter.mm +4 -35
  390. package/ios/TurboModules/ANNTurboModule.mm +104 -33
  391. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.cpp +20 -0
  392. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.h +5 -14
  393. package/lib/module/ARCHITECTURE.md +40 -27
  394. package/lib/module/adapters/NativeANNTurboModule.js.map +1 -1
  395. package/lib/module/api/app/AppRegistry.js +14 -2
  396. package/lib/module/api/app/AppRegistry.js.map +1 -1
  397. package/lib/module/api/app/createNavigation.js +190 -66
  398. package/lib/module/api/app/createNavigation.js.map +1 -1
  399. package/lib/module/api/commands/commands.js +54 -6
  400. package/lib/module/api/commands/commands.js.map +1 -1
  401. package/lib/module/api/events/navigationEvents.js +6 -2
  402. package/lib/module/api/events/navigationEvents.js.map +1 -1
  403. package/lib/module/api/hooks/useNavigation.js +8 -3
  404. package/lib/module/api/hooks/useNavigation.js.map +1 -1
  405. package/lib/module/api/hooks/useSafeAreaInsets.js +4 -3
  406. package/lib/module/api/hooks/useSafeAreaInsets.js.map +1 -1
  407. package/lib/module/api/linking/dispatchedLinks.js +23 -0
  408. package/lib/module/api/linking/dispatchedLinks.js.map +1 -0
  409. package/lib/module/api/linking/linking.js +11 -0
  410. package/lib/module/api/linking/linking.js.map +1 -1
  411. package/lib/module/api/navigation.js.map +1 -1
  412. package/lib/module/api/options/OptionsChain.js +2 -2
  413. package/lib/module/api/screens/arrangement.js +5 -2
  414. package/lib/module/api/screens/arrangement.js.map +1 -1
  415. package/lib/module/api/screens/defineScreen.js +45 -3
  416. package/lib/module/api/screens/defineScreen.js.map +1 -1
  417. package/lib/module/api/screens/nativeScreens.js +31 -6
  418. package/lib/module/api/screens/nativeScreens.js.map +1 -1
  419. package/lib/module/api/screens/registerScreens.js +193 -35
  420. package/lib/module/api/screens/registerScreens.js.map +1 -1
  421. package/lib/module/api/theme/theme.js +5 -0
  422. package/lib/module/api/theme/theme.js.map +1 -1
  423. package/lib/module/engine/commands.js +51 -9
  424. package/lib/module/engine/commands.js.map +1 -1
  425. package/lib/module/engine/layout.js +20 -11
  426. package/lib/module/engine/layout.js.map +1 -1
  427. package/lib/module/engine/nativeScreens.js +9 -0
  428. package/lib/module/engine/nativeScreens.js.map +1 -1
  429. package/lib/module/engine/options.js +49 -15
  430. package/lib/module/engine/options.js.map +1 -1
  431. package/lib/module/engine/optionsChange.js +102 -0
  432. package/lib/module/engine/optionsChange.js.map +1 -0
  433. package/lib/module/engine/places.js +52 -7
  434. package/lib/module/engine/places.js.map +1 -1
  435. package/lib/module/engine/props.js +30 -1
  436. package/lib/module/engine/props.js.map +1 -1
  437. package/lib/module/engine/refresh.js +85 -0
  438. package/lib/module/engine/refresh.js.map +1 -0
  439. package/lib/module/engine/rememberedOptions.js +61 -1
  440. package/lib/module/engine/rememberedOptions.js.map +1 -1
  441. package/lib/module/engine/screens.js +77 -16
  442. package/lib/module/engine/screens.js.map +1 -1
  443. package/lib/module/interfaces/contract/commands.json +101 -0
  444. package/lib/module/interfaces/contract/errors.json +275 -0
  445. package/lib/typescript/adapters/NativeANNTurboModule.d.ts +12 -2
  446. package/lib/typescript/adapters/NativeANNTurboModule.d.ts.map +1 -1
  447. package/lib/typescript/api/app/AppRegistry.d.ts.map +1 -1
  448. package/lib/typescript/api/app/createNavigation.d.ts +8 -3
  449. package/lib/typescript/api/app/createNavigation.d.ts.map +1 -1
  450. package/lib/typescript/api/commands/commands.d.ts.map +1 -1
  451. package/lib/typescript/api/commands/presentation.d.ts +4 -3
  452. package/lib/typescript/api/commands/presentation.d.ts.map +1 -1
  453. package/lib/typescript/api/events/navigationEvents.d.ts +3 -3
  454. package/lib/typescript/api/events/navigationEvents.d.ts.map +1 -1
  455. package/lib/typescript/api/hooks/useNavigation.d.ts +1 -1
  456. package/lib/typescript/api/hooks/useNavigation.d.ts.map +1 -1
  457. package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts +4 -3
  458. package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts.map +1 -1
  459. package/lib/typescript/api/index.d.ts +1 -1
  460. package/lib/typescript/api/index.d.ts.map +1 -1
  461. package/lib/typescript/api/linking/dispatchedLinks.d.ts +7 -0
  462. package/lib/typescript/api/linking/dispatchedLinks.d.ts.map +1 -0
  463. package/lib/typescript/api/linking/linking.d.ts +8 -0
  464. package/lib/typescript/api/linking/linking.d.ts.map +1 -1
  465. package/lib/typescript/api/navigation.d.ts +4 -1
  466. package/lib/typescript/api/navigation.d.ts.map +1 -1
  467. package/lib/typescript/api/options/OptionsChain.d.ts +2 -2
  468. package/lib/typescript/api/screens/arrangement.d.ts +12 -2
  469. package/lib/typescript/api/screens/arrangement.d.ts.map +1 -1
  470. package/lib/typescript/api/screens/defineScreen.d.ts +23 -4
  471. package/lib/typescript/api/screens/defineScreen.d.ts.map +1 -1
  472. package/lib/typescript/api/screens/nativeScreens.d.ts +8 -1
  473. package/lib/typescript/api/screens/nativeScreens.d.ts.map +1 -1
  474. package/lib/typescript/api/screens/registerScreens.d.ts.map +1 -1
  475. package/lib/typescript/api/theme/theme.d.ts +2 -0
  476. package/lib/typescript/api/theme/theme.d.ts.map +1 -1
  477. package/lib/typescript/engine/commands.d.ts +5 -0
  478. package/lib/typescript/engine/commands.d.ts.map +1 -1
  479. package/lib/typescript/engine/layout.d.ts.map +1 -1
  480. package/lib/typescript/engine/nativeScreens.d.ts +5 -0
  481. package/lib/typescript/engine/nativeScreens.d.ts.map +1 -1
  482. package/lib/typescript/engine/options.d.ts +5 -2
  483. package/lib/typescript/engine/options.d.ts.map +1 -1
  484. package/lib/typescript/engine/optionsChange.d.ts +28 -0
  485. package/lib/typescript/engine/optionsChange.d.ts.map +1 -0
  486. package/lib/typescript/engine/places.d.ts +7 -2
  487. package/lib/typescript/engine/places.d.ts.map +1 -1
  488. package/lib/typescript/engine/props.d.ts +8 -1
  489. package/lib/typescript/engine/props.d.ts.map +1 -1
  490. package/lib/typescript/engine/refresh.d.ts +35 -0
  491. package/lib/typescript/engine/refresh.d.ts.map +1 -0
  492. package/lib/typescript/engine/rememberedOptions.d.ts +13 -0
  493. package/lib/typescript/engine/rememberedOptions.d.ts.map +1 -1
  494. package/lib/typescript/engine/screens.d.ts +27 -6
  495. package/lib/typescript/engine/screens.d.ts.map +1 -1
  496. package/lib/typescript/interfaces/ComponentEvents.d.ts +4 -4
  497. package/lib/typescript/interfaces/ComponentEvents.d.ts.map +1 -1
  498. package/lib/typescript/interfaces/Events.d.ts +28 -10
  499. package/lib/typescript/interfaces/Events.d.ts.map +1 -1
  500. package/lib/typescript/interfaces/Options.d.ts +1 -1
  501. package/lib/typescript/interfaces/Options.d.ts.map +1 -1
  502. package/lib/typescript/interfaces/options/animations.d.ts +80 -22
  503. package/lib/typescript/interfaces/options/animations.d.ts.map +1 -1
  504. package/lib/typescript/interfaces/options/bottomTabs.d.ts +21 -7
  505. package/lib/typescript/interfaces/options/bottomTabs.d.ts.map +1 -1
  506. package/lib/typescript/interfaces/options/buttons.d.ts +23 -15
  507. package/lib/typescript/interfaces/options/buttons.d.ts.map +1 -1
  508. package/lib/typescript/interfaces/options/modals.d.ts +34 -26
  509. package/lib/typescript/interfaces/options/modals.d.ts.map +1 -1
  510. package/lib/typescript/interfaces/options/sideMenu.d.ts +23 -6
  511. package/lib/typescript/interfaces/options/sideMenu.d.ts.map +1 -1
  512. package/lib/typescript/interfaces/options/stack.d.ts +17 -3
  513. package/lib/typescript/interfaces/options/stack.d.ts.map +1 -1
  514. package/lib/typescript/interfaces/options/system.d.ts +18 -11
  515. package/lib/typescript/interfaces/options/system.d.ts.map +1 -1
  516. package/lib/typescript/interfaces/options/toolbar.d.ts +2 -2
  517. package/lib/typescript/interfaces/options/topBar.d.ts +68 -38
  518. package/lib/typescript/interfaces/options/topBar.d.ts.map +1 -1
  519. package/metro/acceptPlugin.js +57 -0
  520. package/metro/babelTransformer.js +45 -0
  521. package/metro/index.js +36 -0
  522. package/package.json +3 -1
  523. package/src/ARCHITECTURE.md +40 -27
  524. package/src/adapters/NativeANNTurboModule.ts +12 -2
  525. package/src/api/app/AppRegistry.ts +16 -2
  526. package/src/api/app/createNavigation.ts +203 -69
  527. package/src/api/commands/commands.ts +48 -7
  528. package/src/api/commands/presentation.ts +4 -3
  529. package/src/api/events/navigationEvents.ts +10 -4
  530. package/src/api/hooks/useNavigation.ts +9 -4
  531. package/src/api/hooks/useSafeAreaInsets.ts +4 -3
  532. package/src/api/index.ts +1 -0
  533. package/src/api/linking/dispatchedLinks.ts +18 -0
  534. package/src/api/linking/linking.ts +22 -1
  535. package/src/api/navigation.ts +4 -1
  536. package/src/api/options/OptionsChain.ts +2 -2
  537. package/src/api/screens/arrangement.ts +17 -4
  538. package/src/api/screens/defineScreen.ts +49 -5
  539. package/src/api/screens/nativeScreens.ts +40 -4
  540. package/src/api/screens/registerScreens.tsx +185 -42
  541. package/src/api/theme/theme.ts +5 -0
  542. package/src/engine/commands.ts +70 -13
  543. package/src/engine/layout.ts +27 -11
  544. package/src/engine/nativeScreens.ts +10 -1
  545. package/src/engine/options.ts +45 -19
  546. package/src/engine/optionsChange.ts +107 -0
  547. package/src/engine/places.ts +65 -7
  548. package/src/engine/props.ts +30 -1
  549. package/src/engine/refresh.ts +97 -0
  550. package/src/engine/rememberedOptions.ts +74 -1
  551. package/src/engine/screens.tsx +76 -21
  552. package/src/interfaces/ComponentEvents.ts +4 -4
  553. package/src/interfaces/Events.ts +29 -10
  554. package/src/interfaces/Options.ts +1 -0
  555. package/src/interfaces/contract/commands.json +101 -0
  556. package/src/interfaces/contract/errors.json +275 -0
  557. package/src/interfaces/options/animations.ts +81 -22
  558. package/src/interfaces/options/bottomTabs.ts +21 -7
  559. package/src/interfaces/options/buttons.ts +23 -15
  560. package/src/interfaces/options/modals.ts +34 -26
  561. package/src/interfaces/options/sideMenu.ts +24 -6
  562. package/src/interfaces/options/stack.ts +17 -3
  563. package/src/interfaces/options/system.ts +18 -11
  564. package/src/interfaces/options/toolbar.ts +2 -2
  565. package/src/interfaces/options/topBar.ts +68 -38
  566. package/android/src/main/java/dev/apexnative/navigation/react/ArrangementStates.kt +0 -41
  567. package/android/src/main/java/dev/apexnative/navigation/react/ScreenInsets.kt +0 -69
  568. package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationStateReporter.kt +0 -62
  569. package/android/src/main/java/dev/apexnative/navigation/react/events/StateHold.kt +0 -62
  570. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowPlacer.kt +0 -223
  571. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStub.kt +0 -31
  572. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMatrixAnimator.kt +0 -138
  573. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PlainViewAnimator.kt +0 -88
  574. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PropertyAnimatorCreator.kt +0 -33
  575. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ReactImageAnimator.kt +0 -66
  576. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextChangeAnimator.kt +0 -179
  577. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewChangeAnimator.kt +0 -139
  578. package/ios/Layouts/Screen/ANNScreenInsets.h +0 -30
  579. package/ios/Layouts/Screen/ANNScreenInsets.mm +0 -68
  580. package/ios/Layouts/Tabs/ANNTabsPreloadWindow.h +0 -27
  581. package/ios/Layouts/Tabs/ANNTabsPreloadWindow.mm +0 -55
@@ -1,19 +1,8 @@
1
1
  package dev.apexnative.navigation.utils
2
2
 
3
3
  import android.content.Context
4
- import android.content.res.Resources
5
- import android.graphics.BitmapFactory
6
- import android.graphics.drawable.BitmapDrawable
7
4
  import android.graphics.drawable.Drawable
8
- import android.net.Uri
9
- import android.os.StrictMode
10
- import androidx.core.content.ContextCompat
11
- import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper
12
- import java.io.FileInputStream
13
- import java.io.FileNotFoundException
14
5
  import java.io.IOException
15
- import java.io.InputStream
16
- import java.net.URL
17
6
 
18
7
  /** What an image loads into: [onComplete] with the image, or [onError] when it can't load. Main thread. */
19
8
  open class ImageLoadingListenerAdapter {
@@ -23,90 +12,19 @@ open class ImageLoadingListenerAdapter {
23
12
  }
24
13
 
25
14
  /**
26
- * Loads the images and icons of the options when they apply: synchronously on the main thread, without a cache, each
27
- * image its own mutable copy. A `file:` address is a file; anything else first a drawable of the app by name (as React
28
- * Native's images by resource name: release builds' assets, `{ android }` icons). Not found while the app is in
29
- * development: the address is read as a stream, Metro's asset over the network (network on the main thread allowed for
30
- * that read only) or through the content resolver. A remote address that is not Metro's asset is never loaded. A
31
- * failure never ends the app: the listener's [ImageLoadingListenerAdapter.onError], the log, and React Native's red
32
- * screen in development.
15
+ * Loads an image or an icon of the options at once, through the shared cache of [OptionImages]: each image its own
16
+ * mutable copy. For the places whose first frame needs the image (the top bar's buttons, the back button, menus, search
17
+ * suggestions); a place that can show it when ready asks through [ImageRequests]. A failure never ends the app: the
18
+ * listener's [ImageLoadingListenerAdapter.onError], and one warning per address.
33
19
  */
34
20
  class ImageLoader {
35
21
  /** Loads [uri] and gives it to [listener] before returning. Main thread. */
36
22
  fun loadIcon(context: Context, uri: String, listener: ImageLoadingListenerAdapter) {
37
- val drawable = try {
38
- load(context, uri)
39
- } catch (e: Exception) {
40
- val reason = if (e is LoadFailure) "" else ": ${e.message ?: e.javaClass.simpleName}"
41
- DevelopmentLog.error("Could not load image $uri$reason${(e as? LoadFailure)?.why.orEmpty()}", e)
42
- listener.onError(e)
23
+ val drawable = OptionImages.load(context, uri)
24
+ if (drawable == null) {
25
+ listener.onError(IOException("Could not load image $uri"))
43
26
  return
44
27
  }
45
28
  listener.onComplete(drawable)
46
29
  }
47
-
48
- private fun load(context: Context, uri: String): Drawable {
49
- if (uri.startsWith(FILE_SCHEME)) return decode(context) { FileInputStream(Uri.parse(uri).path) }
50
- resourceDrawable(context, uri)?.let { return it }
51
- if (!DevelopmentLog.isDevelopment) throw LoadFailure("")
52
- val address = Uri.parse(uri)
53
- return when (address.scheme) {
54
- "http", "https" -> {
55
- if (!isMetroAsset(address)) throw LoadFailure(": remote images are not supported in options")
56
- withNetworkOnMainThread { decode(context) { URL(uri).openStream() } }
57
- }
58
- else -> decode(context) {
59
- context.contentResolver.openInputStream(address) ?: throw FileNotFoundException(uri)
60
- }
61
- }
62
- }
63
-
64
- // A drawable of the app by name, its own copy; none when the app has none by that name.
65
- private fun resourceDrawable(context: Context, name: String): Drawable? {
66
- val id = ResourceDrawableIdHelper.getResourceDrawableId(context, name)
67
- if (id <= 0) return null
68
- return try {
69
- ContextCompat.getDrawable(context, id)?.mutate()
70
- } catch (e: Resources.NotFoundException) {
71
- null
72
- }
73
- }
74
-
75
- // The image of the stream [open] gives, closed after the read, also on an error; one it can't decode fails, and so
76
- // does one too large for the memory: that is a load error too, never the end of the app.
77
- private fun decode(context: Context, open: () -> InputStream): Drawable {
78
- val decoded = try {
79
- open().use { BitmapFactory.decodeStream(it) }
80
- } catch (e: OutOfMemoryError) {
81
- throw LoadFailure(": it is too large to decode")
82
- }
83
- val bitmap = decoded ?: throw LoadFailure(": it can't be decoded")
84
- return BitmapDrawable(context.resources, bitmap)
85
- }
86
-
87
- // A failure the loader names itself: `Could not load image <source>`, then [why].
88
- private class LoadFailure(val why: String) : IOException("Could not load image$why")
89
-
90
- // Metro's asset: an address of the server the JavaScript bundle came from, under `/assets/`.
91
- private fun isMetroAsset(address: Uri): Boolean {
92
- val bundle = DevelopmentLog.bundleUrl?.let(Uri::parse) ?: return false
93
- return address.host == bundle.host && address.port == bundle.port &&
94
- address.path.orEmpty().startsWith(ASSETS_PATH)
95
- }
96
-
97
- // Reading from the network on the main thread for [read] only; the thread's policy comes back, also on an error.
98
- private fun <T> withNetworkOnMainThread(read: () -> T): T {
99
- val policy = StrictMode.getThreadPolicy()
100
- StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder(policy).permitNetwork().build())
101
- try {
102
- return read()
103
- } finally {
104
- StrictMode.setThreadPolicy(policy)
105
- }
106
- }
107
-
108
- private companion object {
109
- const val FILE_SCHEME = "file:"
110
- const val ASSETS_PATH = "/assets/"
111
- }
112
30
  }
@@ -0,0 +1,76 @@
1
+ package dev.apexnative.navigation.utils
2
+
3
+ import android.graphics.drawable.Drawable
4
+
5
+ /** Where the images of the options come from, for one context: [OptionImages.source], or a fake in the tests. */
6
+ internal interface ImageSource {
7
+ /** The key of [uri] in the context's configuration now; for a `file:` uri it reads the file's version. */
8
+ fun key(uri: String): ImageKey
9
+
10
+ /** A copy of the image of [key] when the cache has it, none otherwise; never loads. */
11
+ fun cached(key: ImageKey): Drawable?
12
+
13
+ /** A copy of the image of [key], from the cache or loaded on the caller's thread; none on a failure. */
14
+ fun now(key: ImageKey): Drawable?
15
+
16
+ /** Whether [uri] can load off the main thread: a file or a drawable of the app. */
17
+ fun loadsLater(uri: String): Boolean
18
+
19
+ /** Loads [key] off the main thread and gives a copy of it, or none on a failure, to [done] on the main thread. */
20
+ fun later(key: ImageKey, done: (Drawable?) -> Unit)
21
+ }
22
+
23
+ /**
24
+ * The images that the places of a view asked for (an item's icon, a button's icon), by place [P]: what the cache has
25
+ * comes at once; what it doesn't, when the place can show it later, loads off the main thread and comes when ready;
26
+ * everything else loads at once. The last request of a place wins: a load that arrives after the place asked again,
27
+ * or after [forget] or [clear], is dropped. A load that fails gives the place no image, as an option without one:
28
+ * the image it showed before doesn't stay. A request builds the key of its image once (a file's version is read once).
29
+ * Main thread only.
30
+ */
31
+ internal class ImageRequests<P : Any>(private val source: ImageSource) {
32
+ // The open load of each place: its number, which a later request of the place replaces.
33
+ private val waiting = HashMap<P, Long>()
34
+ private var last = 0L
35
+
36
+ /** The key of [uri] now, for a caller that compares it before it asks ([request] with the key). */
37
+ fun key(uri: String): ImageKey = source.key(uri)
38
+
39
+ /** [request] for the image of [uri], its key built here. */
40
+ fun request(place: P, uri: String, mayWait: Boolean, show: (Drawable?) -> Unit) =
41
+ request(place, source.key(uri), mayWait, show)
42
+
43
+ /**
44
+ * Gives [show] the image of [key] for [place]: now when the cache has it, or when the place can't wait for it
45
+ * ([mayWait] false: the first frame needs it) or the uri can't load off the main thread (Metro's address, a content
46
+ * uri); otherwise later, unless [place] asks again first. Null when it doesn't load: the place shows none.
47
+ */
48
+ fun request(place: P, key: ImageKey, mayWait: Boolean, show: (Drawable?) -> Unit) {
49
+ waiting.remove(place)
50
+ source.cached(key)?.let {
51
+ show(it)
52
+ return
53
+ }
54
+ if (!mayWait || !source.loadsLater(key.uri)) {
55
+ show(source.now(key))
56
+ return
57
+ }
58
+ val number = ++last
59
+ waiting[place] = number
60
+ source.later(key) { image ->
61
+ if (waiting[place] != number) return@later
62
+ waiting.remove(place)
63
+ show(image)
64
+ }
65
+ }
66
+
67
+ /** The place shows no image of the options now: a load it asked for earlier is dropped. */
68
+ fun forget(place: P) {
69
+ waiting.remove(place)
70
+ }
71
+
72
+ /** The view goes: every open load is dropped. */
73
+ fun clear() {
74
+ waiting.clear()
75
+ }
76
+ }
@@ -28,7 +28,7 @@ internal object MaterialTheme {
28
28
  private val wrappers = WeakHashMap<Context, WeakReference<Context>>()
29
29
  // Themes of the navigation's own views, each made once over the activity's with a style of its own.
30
30
  private val followers = WeakHashMap<Context, Int>()
31
- // The popup theme of the bar's toolbars per activity: the app's theme doesn't change while the activity lives.
31
+ // The popup theme of the bar's "⋮" per activity: the app's theme doesn't change while the activity lives.
32
32
  private val popupThemes = WeakHashMap<Activity, Int>()
33
33
 
34
34
  fun context(context: Context): Context {
@@ -38,11 +38,10 @@ internal object MaterialTheme {
38
38
  }
39
39
 
40
40
  /**
41
- * The popup theme of the top bar's toolbars, for "⋮", set on them before their menu is made. None when the app's
42
- * theme follows light and dark: the menu takes the bar's own theme, which [rebase] keeps in the current mode, with
43
- * the app's colors. With a Material 3 theme fixed to light or to dark, a day/night overlay that gives the menu the
44
- * current mode's colors where the theme shows the other mode. Android makes the menu's theme from it at the menu's
45
- * first opening, in the mode of that moment, and no public API makes it again for a later switch.
41
+ * The popup theme of the top bar's "⋮", over the bar's theme at each opening of its popup, in the mode of that
42
+ * moment. None when the app's theme follows light and dark: the menu takes the bar's own theme, which [rebase]
43
+ * keeps in the current mode, with the app's colors. With a Material 3 theme fixed to light or to dark, a day/night
44
+ * overlay that gives the menu the current mode's colors where the theme shows the other mode.
46
45
  */
47
46
  fun popupTheme(context: Context): Int {
48
47
  val activity = activityOf(context) ?: return 0
@@ -0,0 +1,262 @@
1
+ package dev.apexnative.navigation.utils
2
+
3
+ import android.content.ComponentCallbacks2
4
+ import android.content.Context
5
+ import android.content.res.Configuration
6
+ import android.content.res.Resources
7
+ import android.graphics.BitmapFactory
8
+ import android.graphics.drawable.BitmapDrawable
9
+ import android.graphics.drawable.Drawable
10
+ import android.net.Uri
11
+ import android.os.StrictMode
12
+ import android.util.LruCache
13
+ import androidx.core.content.ContextCompat
14
+ import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper
15
+ import java.io.FileInputStream
16
+ import java.io.FileNotFoundException
17
+ import java.io.IOException
18
+ import java.io.InputStream
19
+ import java.net.URL
20
+ import java.util.Collections
21
+ import java.util.concurrent.ExecutorService
22
+ import java.util.concurrent.Executors
23
+
24
+ /**
25
+ * The images and icons of the options, every one of them (bar buttons and their menus, the back button, search
26
+ * suggestions, tab icons, the FAB): one cache for the app, by [ImageKey], sized by the bytes of its images and let go
27
+ * when the system is low on memory with the app in the background ([clearsOnTrim]), not each time the app's UI hides;
28
+ * each caller gets its own mutable copy. The images don't depend on the JavaScript, so a reload keeps them.
29
+ *
30
+ * A `file:` address is a file; anything else first a drawable of the app by name (as React Native's images by resource
31
+ * name: release builds' assets, `{ android }` icons). Those two load on the caller's thread ([load]) or on a
32
+ * background thread of their own ([loadLater]). Not found while the app is in development: the address is read as a
33
+ * stream on the main thread, Metro's asset over the network (network on the main thread allowed for that read only)
34
+ * or through the content resolver. A remote address that is not Metro's asset is never loaded. A failure (a missing
35
+ * file or drawable, data that doesn't decode, an image too large for the memory) never ends the app: no image, and one
36
+ * warning per address in the log (and LogBox in development).
37
+ *
38
+ * A theme attribute inside a drawable of the app is resolved against the theme of the context that loaded it first.
39
+ * Main thread, unless a member says otherwise.
40
+ */
41
+ internal object OptionImages {
42
+ private val cache = object : LruCache<ImageKey, Entry>(maxBytes()) {
43
+ override fun sizeOf(key: ImageKey, value: Entry) = value.bytes
44
+ }
45
+
46
+ // The addresses already named in a warning: one each.
47
+ private val warned: MutableSet<String> = Collections.synchronizedSet(HashSet())
48
+
49
+ // The loads off the main thread under way, with who waits for each.
50
+ private val loading = HashMap<ImageKey, MutableList<Waiter>>()
51
+
52
+ private val background: ExecutorService by lazy {
53
+ Executors.newSingleThreadExecutor { task -> Thread(task, THREAD_NAME).apply { isDaemon = true } }
54
+ }
55
+
56
+ @Volatile
57
+ private var listening = false
58
+
59
+ /** The cache and the loads for [context]: the source of an [ImageRequests]. */
60
+ fun source(context: Context): ImageSource = object : ImageSource {
61
+ override fun key(uri: String) = ImageKey.of(context, uri)
62
+
63
+ override fun cached(key: ImageKey) = cached(context, key)
64
+
65
+ override fun now(key: ImageKey) = load(context, key)
66
+
67
+ override fun loadsLater(uri: String) = loadsLater(context, uri)
68
+
69
+ override fun later(key: ImageKey, done: (Drawable?) -> Unit) = loadLater(context, key, done)
70
+ }
71
+
72
+ /** A copy of the image of [key] when the cache has it. Any thread. */
73
+ fun cached(context: Context, key: ImageKey): Drawable? = cache.get(key)?.copy(context)
74
+
75
+ /** A copy of the image of [uri], from the cache or loaded on the caller's thread; none on a failure. */
76
+ fun load(context: Context, uri: String): Drawable? = load(context, ImageKey.of(context, uri))
77
+
78
+ /**
79
+ * A copy of the image of [key] (built in the configuration of [context]), from the cache or loaded on the caller's
80
+ * thread; none on a failure.
81
+ */
82
+ fun load(context: Context, key: ImageKey): Drawable? {
83
+ listen(context)
84
+ cache.get(key)?.let { return it.copy(context) }
85
+ val loaded = decodeOrWarn(context, key.uri) ?: return null
86
+ return keep(key, loaded)?.copy(context) ?: loaded
87
+ }
88
+
89
+ /** Whether [uri] loads off the main thread: a file, or a drawable the app has by that name. Any thread. */
90
+ fun loadsLater(context: Context, uri: String): Boolean =
91
+ uri.startsWith(FILE_SCHEME) || ResourceDrawableIdHelper.getResourceDrawableId(context, uri) > 0
92
+
93
+ /**
94
+ * Loads [key] (built in the configuration of [context]) on the background thread and gives [done] a copy of it, or
95
+ * none on a failure, on the main thread; one load for all who ask for the same image meanwhile. Only for what
96
+ * [loadsLater].
97
+ */
98
+ fun loadLater(context: Context, key: ImageKey, done: (Drawable?) -> Unit) {
99
+ listen(context)
100
+ val waiters = loading[key]
101
+ if (waiters != null) {
102
+ waiters.add(Waiter(context, done))
103
+ return
104
+ }
105
+ loading[key] = mutableListOf(Waiter(context, done))
106
+ background.execute {
107
+ val loaded = decodeOrWarn(context, key.uri)
108
+ val entry = loaded?.let { keep(key, it) }
109
+ UiThread.post { deliver(key, loaded, entry) }
110
+ }
111
+ }
112
+
113
+ /** Lets every image of the cache go. Any thread. */
114
+ fun clear() {
115
+ cache.evictAll()
116
+ }
117
+
118
+ /**
119
+ * Whether the cache lets its images go at a trim of [level]: when the system is low on memory with the app in the
120
+ * background (`TRIM_MEMORY_BACKGROUND` and above), not at `TRIM_MEMORY_UI_HIDDEN`, which comes each time the app
121
+ * goes to the background: its icons are there when it comes back.
122
+ */
123
+ fun clearsOnTrim(level: Int): Boolean = level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
124
+
125
+ // Each waiter gets a copy of its own; an image the cache can't keep (no constant state) goes to the first only,
126
+ // the others load it again.
127
+ private fun deliver(key: ImageKey, loaded: Drawable?, entry: Entry?) {
128
+ val waiters = loading.remove(key) ?: return
129
+ waiters.forEachIndexed { index, waiter ->
130
+ val image = when {
131
+ loaded == null -> null
132
+ entry != null -> entry.copy(waiter.context)
133
+ index == 0 -> loaded
134
+ else -> load(waiter.context, key)
135
+ }
136
+ waiter.done(image)
137
+ }
138
+ }
139
+
140
+ // Into the cache, when the image can be copied; the entry it keeps. Any thread.
141
+ private fun keep(key: ImageKey, image: Drawable): Entry? {
142
+ val state = image.constantState ?: return null
143
+ return Entry(state, bytesOf(image)).also { cache.put(key, it) }
144
+ }
145
+
146
+ private fun bytesOf(image: Drawable): Int {
147
+ if (image is BitmapDrawable) image.bitmap?.let { return it.allocationByteCount }
148
+ // A drawable that draws itself (a vector) keeps a picture of its own size when it is drawn.
149
+ return image.intrinsicWidth.coerceAtLeast(1) * image.intrinsicHeight.coerceAtLeast(1) * BYTES_PER_PIXEL
150
+ }
151
+
152
+ // The image of [uri], or none and one warning per address. Any thread.
153
+ private fun decodeOrWarn(context: Context, uri: String): Drawable? = try {
154
+ decode(context, uri)
155
+ } catch (e: Exception) {
156
+ warnOnce(uri, (e as? LoadFailure)?.why ?: ": ${e.message ?: e.javaClass.simpleName}")
157
+ null
158
+ } catch (e: OutOfMemoryError) {
159
+ warnOnce(uri, ": it is too large to decode")
160
+ null
161
+ }
162
+
163
+ private fun warnOnce(uri: String, why: String) {
164
+ if (warned.add(uri)) DevelopmentLog.warn("Could not load image $uri$why")
165
+ }
166
+
167
+ private fun decode(context: Context, uri: String): Drawable {
168
+ if (uri.startsWith(FILE_SCHEME)) return decodeStream(context) { FileInputStream(Uri.parse(uri).path) }
169
+ resourceDrawable(context, uri)?.let { return it }
170
+ if (!DevelopmentLog.isDevelopment) throw LoadFailure("")
171
+ val address = Uri.parse(uri)
172
+ return when (address.scheme) {
173
+ "http", "https" -> {
174
+ if (!isMetroAsset(address)) throw LoadFailure(": remote images are not supported in options")
175
+ withNetworkOnMainThread { decodeStream(context) { URL(uri).openStream() } }
176
+ }
177
+ else -> decodeStream(context) {
178
+ context.contentResolver.openInputStream(address) ?: throw FileNotFoundException(uri)
179
+ }
180
+ }
181
+ }
182
+
183
+ // A drawable of the app by name; none when the app has none by that name.
184
+ private fun resourceDrawable(context: Context, name: String): Drawable? {
185
+ val id = ResourceDrawableIdHelper.getResourceDrawableId(context, name)
186
+ if (id <= 0) return null
187
+ return try {
188
+ ContextCompat.getDrawable(context, id)
189
+ } catch (e: Resources.NotFoundException) {
190
+ null
191
+ }
192
+ }
193
+
194
+ // The image of the stream [open] gives, closed after the read, also on an error; one it can't decode fails, and so
195
+ // does one too large for the memory.
196
+ private fun decodeStream(context: Context, open: () -> InputStream): Drawable {
197
+ val decoded = try {
198
+ open().use { BitmapFactory.decodeStream(it) }
199
+ } catch (e: OutOfMemoryError) {
200
+ throw LoadFailure(": it is too large to decode")
201
+ }
202
+ val bitmap = decoded ?: throw LoadFailure(": it can't be decoded")
203
+ return BitmapDrawable(context.resources, bitmap)
204
+ }
205
+
206
+ // Metro's asset: an address of the server the JavaScript bundle came from, under `/assets/`.
207
+ private fun isMetroAsset(address: Uri): Boolean {
208
+ val bundle = DevelopmentLog.bundleUrl?.let(Uri::parse) ?: return false
209
+ return address.host == bundle.host && address.port == bundle.port &&
210
+ address.path.orEmpty().startsWith(ASSETS_PATH)
211
+ }
212
+
213
+ // Reading from the network on the main thread for [read] only; the thread's policy comes back, also on an error.
214
+ private fun <T> withNetworkOnMainThread(read: () -> T): T {
215
+ val policy = StrictMode.getThreadPolicy()
216
+ StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder(policy).permitNetwork().build())
217
+ try {
218
+ return read()
219
+ } finally {
220
+ StrictMode.setThreadPolicy(policy)
221
+ }
222
+ }
223
+
224
+ // The cache lets its images go when the system is low on memory ([clearsOnTrim]): they load again when asked.
225
+ private fun listen(context: Context) {
226
+ if (listening) return
227
+ synchronized(this) {
228
+ if (listening) return
229
+ listening = true
230
+ }
231
+ context.applicationContext.registerComponentCallbacks(object : ComponentCallbacks2 {
232
+ override fun onTrimMemory(level: Int) {
233
+ if (clearsOnTrim(level)) clear()
234
+ }
235
+
236
+ override fun onConfigurationChanged(newConfig: Configuration) = Unit
237
+
238
+ @Deprecated("Android 14 deprecates it; onTrimMemory comes with it")
239
+ override fun onLowMemory() = clear()
240
+ })
241
+ }
242
+
243
+ // A sixteenth of the app's heap, at most 16 MB: the options' icons are small.
244
+ private fun maxBytes(): Int = (Runtime.getRuntime().maxMemory() / HEAP_PART).coerceAtMost(MAX_BYTES).toInt()
245
+
246
+ // An image the cache keeps: what makes its copies, and its size.
247
+ private class Entry(val state: Drawable.ConstantState, val bytes: Int) {
248
+ fun copy(context: Context): Drawable = state.newDrawable(context.resources).mutate()
249
+ }
250
+
251
+ private class Waiter(val context: Context, val done: (Drawable?) -> Unit)
252
+
253
+ // A failure the loader names itself: `Could not load image <source>`, then [why].
254
+ private class LoadFailure(val why: String) : IOException("Could not load image$why")
255
+
256
+ private const val FILE_SCHEME = "file:"
257
+ private const val ASSETS_PATH = "/assets/"
258
+ private const val THREAD_NAME = "ApexNavigation images"
259
+ private const val BYTES_PER_PIXEL = 4
260
+ private const val HEAP_PART = 16L
261
+ private const val MAX_BYTES = 16L * 1024 * 1024
262
+ }
@@ -0,0 +1,36 @@
1
+ package dev.apexnative.navigation.utils
2
+
3
+ import android.animation.ValueAnimator
4
+ import android.annotation.SuppressLint
5
+ import android.content.Context
6
+ import android.os.Build
7
+ import android.provider.Settings
8
+ import dev.apexnative.navigation.NavigationApplication
9
+
10
+ /**
11
+ * Whether the system plays no animations: "Remove animations" in the accessibility settings, or the animator duration
12
+ * scale at 0 in the developer options. Then a transition doesn't wait for its elements' targets and images and moves no
13
+ * element, and the side menu opens and closes at once. Any thread.
14
+ */
15
+ internal object SystemAnimations {
16
+ /**
17
+ * The animations are off now; [context] reads the scale below Android 8, else the application's. Lint can't see
18
+ * that the decision calls `areAnimatorsEnabled` (API 26) only from Android 8.
19
+ */
20
+ @SuppressLint("NewApi")
21
+ fun areOff(context: Context? = null): Boolean =
22
+ areOff(Build.VERSION.SDK_INT, { ValueAnimator.areAnimatorsEnabled() }) { durationScaleOf(context) }
23
+
24
+ /**
25
+ * The decision: from Android 8 the animator's own answer ([animatorsEnabled]), which follows both settings;
26
+ * below it the duration scale ([durationScale]) at 0.
27
+ */
28
+ fun areOff(sdk: Int, animatorsEnabled: () -> Boolean, durationScale: () -> Float): Boolean =
29
+ if (sdk >= Build.VERSION_CODES.O) !animatorsEnabled() else durationScale() == 0f
30
+
31
+ // Without a context and before the application started (the unit tests), the animations play.
32
+ private fun durationScaleOf(context: Context?): Float {
33
+ val resolver = (context ?: NavigationApplication.instanceOrNull)?.contentResolver ?: return 1f
34
+ return Settings.Global.getFloat(resolver, Settings.Global.ANIMATOR_DURATION_SCALE, 1f)
35
+ }
36
+ }
@@ -22,8 +22,8 @@ object UiUtils {
22
22
  fun pxToDp(context: Context, px: Float): Float = px / context.resources.displayMetrics.density
23
23
 
24
24
  /**
25
- * A size of the options in dp, in whole pixels of the screen of [context]: times `densityDpi / 160`, the fraction
26
- * of a pixel dropped; a size of 0 or less is not converted.
25
+ * A size of the options in dp, in whole pixels of the screen of [context]: times `densityDpi / 160`, rounded to the
26
+ * nearest pixel only here, as iOS places a size in points on whole pixels; a size of 0 or less is not converted.
27
27
  */
28
28
  @JvmStatic
29
29
  fun dpToPixels(context: Context, dp: Double): Int = dpToPixels(dp, context.resources.displayMetrics.densityDpi)
@@ -31,7 +31,7 @@ object UiUtils {
31
31
  /** [dp] in whole pixels at [densityDpi], as [dpToPixels] converts it. */
32
32
  @JvmStatic
33
33
  fun dpToPixels(dp: Double, densityDpi: Int): Int =
34
- if (dp <= 0) dp.toInt() else (dp * densityDpi / BASE_DENSITY_DPI).toInt()
34
+ if (dp <= 0) dp.toInt() else (dp * densityDpi / BASE_DENSITY_DPI).roundToInt()
35
35
 
36
36
  /**
37
37
  * A font size of the options in sp, in pixels of the screen of [context]: it follows the system's text scale,
@@ -59,7 +59,9 @@ private fun ViewController<*>.hostIsShown(): Boolean {
59
59
  * Runs [mounted] as the content of this screen's slot mounts into its container, and [start] on the pre-draw of that
60
60
  * frame: after React Native applied the whole mount, before the frame is drawn. At once if the content has mounted,
61
61
  * after [DRAW_WAIT_LIMIT] if it never does; while [waiting] holds. A screen prepared for its push was rendered at its
62
- * size and insets before: in that frame it is whole.
62
+ * size and insets before, so it is whole from that frame on; its push doesn't start in that frame: [start] hands it to
63
+ * the stack's queue, which starts the transition on a later turn, behind the calls JavaScript made before
64
+ * (`PendingCalls`), so the `mergeOptions` of the mount's commit has applied.
63
65
  */
64
66
  fun ViewController<*>.whenContentMounted(waiting: () -> Boolean, mounted: () -> Unit, start: () -> Unit) {
65
67
  var done = false
@@ -26,16 +26,3 @@ val View.borderRadius: Float
26
26
  */
27
27
  internal fun resolveBorderRadius(radius: LengthPercentage, width: Int, density: Float): Float =
28
28
  (radius.resolve(width / density) * density).coerceAtLeast(0f)
29
-
30
- /** The scale the parents of [view] give it, along x and along y: a view in a scaled parent shows smaller. */
31
- fun computeInheritedScale(view: View): Pair<Float, Float> {
32
- var scaleX = 1f
33
- var scaleY = 1f
34
- var parent = view.parent as? View
35
- while (parent != null) {
36
- scaleX *= parent.scaleX
37
- scaleY *= parent.scaleY
38
- parent = parent.parent as? View
39
- }
40
- return scaleX to scaleY
41
- }
@@ -9,7 +9,8 @@ import androidx.window.layout.WindowMetricsCalculator
9
9
  import dev.apexnative.navigation.NavigationActivity
10
10
  import dev.apexnative.navigation.options.DefaultOptions
11
11
  import dev.apexnative.navigation.options.Options
12
- import dev.apexnative.navigation.react.ArrangementStates
12
+ import dev.apexnative.navigation.react.ScreenEnvironment
13
+ import dev.apexnative.navigation.react.events.EventEmitter
13
14
  import dev.apexnative.navigation.utils.SystemUiUtils
14
15
  import dev.apexnative.navigation.utils.WindowFolds
15
16
  import dev.apexnative.navigation.viewcontrollers.child.ChildController
@@ -145,12 +146,14 @@ class ArrangementController internal constructor(
145
146
  val overlay = plan.layout == ArrangementPlan.Layout.OVERLAY
146
147
  val single = plan.layout == ArrangementPlan.Layout.SINGLE
147
148
  if (primary is ComponentViewController) {
148
- val state = ArrangementStates.State(PRIMARY, layout, front = overlay, hidden = false)
149
- ArrangementStates.set(activity, primary.id, state, notify)
149
+ val state = ScreenEnvironment.Arrangement(PRIMARY, layout, front = overlay, hidden = false)
150
+ val changes = ScreenEnvironment.changesOf(EventEmitter.of(primary.jsGeneration))
151
+ ScreenEnvironment.setArrangement(primary.id, state, notify, changes)
150
152
  }
151
153
  if (secondary is ComponentViewController) {
152
- val state = ArrangementStates.State(SECONDARY, layout, front = false, hidden = single)
153
- ArrangementStates.set(activity, secondary.id, state, notify)
154
+ val state = ScreenEnvironment.Arrangement(SECONDARY, layout, front = false, hidden = single)
155
+ val changes = ScreenEnvironment.changesOf(EventEmitter.of(secondary.jsGeneration))
156
+ ScreenEnvironment.setArrangement(secondary.id, state, notify, changes)
154
157
  }
155
158
  }
156
159
 
@@ -243,9 +246,9 @@ class ArrangementController internal constructor(
243
246
  // The stack keeps the bar's title, buttons and search by the view of its screen on top: they go with the pair.
244
247
  if (!isDestroyed && peekView() != null) performOnParentController { it.onChildDestroyed(this) }
245
248
  folds?.removeListener(onFoldsChanged)
246
- ArrangementStates.remove(primary.id)
247
- ArrangementStates.remove(secondary.id)
248
249
  shownChildren.containerDisappeared()
250
+ // The screens go with the pair: each clears its own environment, its arrangement too, unless its id is
251
+ // another's now.
249
252
  super.destroy()
250
253
  }
251
254
 
@@ -11,7 +11,10 @@ data class ArrangementDefinition(
11
11
  val axes: Axes,
12
12
  /** `split`: the primary's share along the split, 0–1, where a fold doesn't decide. */
13
13
  val fraction: Float,
14
- /** `overlay`: the edge the primary takes when the pair goes side by side at a fold. */
14
+ /**
15
+ * The edge the primary takes. `split`: leading or top puts it first, trailing or bottom second; `overlay`: its edge
16
+ * when the pair goes side by side at a fold.
17
+ */
15
18
  val primaryEdge: Edge,
16
19
  /** What a window too small for a pair shows. */
17
20
  val compact: Compact,
@@ -36,8 +39,9 @@ data class ArrangementDefinition(
36
39
  @JvmStatic
37
40
  fun parse(data: JSONObject): ArrangementDefinition {
38
41
  val fraction = data.optDouble("fraction", DEFAULT_FRACTION).takeUnless { it.isNaN() } ?: DEFAULT_FRACTION
42
+ val style = if (data.optString("style") == "overlay") Style.OVERLAY else Style.SPLIT
39
43
  return ArrangementDefinition(
40
- style = if (data.optString("style") == "overlay") Style.OVERLAY else Style.SPLIT,
44
+ style = style,
41
45
  axes = when (data.optString("axes")) {
42
46
  "horizontal" -> Axes.HORIZONTAL
43
47
  "vertical" -> Axes.VERTICAL
@@ -48,7 +52,9 @@ data class ArrangementDefinition(
48
52
  "leading" -> Edge.LEADING
49
53
  "top" -> Edge.TOP
50
54
  "bottom" -> Edge.BOTTOM
51
- else -> Edge.TRAILING
55
+ "trailing" -> Edge.TRAILING
56
+ // The default of each style: the primary first in a split, at the trailing side of an overlay.
57
+ else -> if (style == Style.SPLIT) Edge.LEADING else Edge.TRAILING
52
58
  },
53
59
  compact = if (data.optString("compact") == "pair") Compact.PAIR else Compact.PRIMARY,
54
60
  )