@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,70 +1,85 @@
1
1
  package dev.apexnative.navigation.views.element.animators
2
2
 
3
- import android.animation.Animator
4
3
  import android.view.View
5
4
  import android.widget.ImageView
6
- import com.facebook.react.views.image.ReactImageView
7
5
  import com.facebook.react.views.text.ReactTextView
8
- import com.facebook.react.views.view.ReactViewGroup
9
6
  import dev.apexnative.navigation.options.SharedElementTransitionOptions
10
7
  import dev.apexnative.navigation.views.animations.AnimationRules
11
8
  import dev.apexnative.navigation.views.animations.Curves
12
- import dev.apexnative.navigation.views.element.TransitionLayer
9
+ import dev.apexnative.navigation.views.element.elementSkipped
10
+ import dev.apexnative.navigation.views.element.pairName
13
11
 
14
12
  /**
15
- * The animator of a shared element by the kinds of its two views, chosen by explicit classes, never by reflection:
16
- * texts (`TextChangeAnimator`, the module), React views with children (`ViewChangeAnimator`, the module; a failed
17
- * picture flies as a view without children), React images ([ReactImageAnimator]), other images ([ImageMatrixAnimator]),
18
- * any other view ([PlainViewAnimator]). The animator gets the pair's duration (else the fallback, the screen's fade),
19
- * its delay and its curve here, each of its own (a spring in real time); an `AnimatorSet` around it never sets them.
20
- * Main thread only.
13
+ * The flight of a shared pair, as on iOS: a copy drawn in the transition's layer, chosen by the kinds of the two views,
14
+ * by explicit classes, never by reflection — texts ([TextMorph]), images ([ImageMorph]; one without an image to fit
15
+ * flies as a view), any other views ([ViewMorph]). The views themselves are neither moved nor changed. The animator
16
+ * gets the pair's duration (else the fallback, the screen's fade), its delay and its curve here, each of its own (a
17
+ * spring in real time); an `AnimatorSet` around it never sets them. Main thread only.
21
18
  */
22
19
  internal object SharedAnimatorFactory {
23
- /**
24
- * A pair's animator, and how it shows the pair: by pictures in the layer's overlay while `to` is hidden (the
25
- * modules), or by moving `to` itself, which shows from the start of the flight.
26
- */
27
- class Flight(val animator: Animator, val drawsPictures: Boolean)
20
+ /** A pair's animator and the copy it moves. */
21
+ class Flight(val animator: MoveAnimator, val picture: FlightPicture)
28
22
 
29
23
  /**
30
- * The flight of the pair [from] → [to]; [to] is in [layer] at its margins, at its real alpha (the pictures are
31
- * taken now). [toParent] is the parent [to] had in its screen. None: the pair doesn't fly (a text that didn't
32
- * change, a picture that can't be taken, no place).
24
+ * The flight of the pair [from] → [to] in [layer], its pictures taken now; a view or an image shows only the part
25
+ * its parents up to the view of its screen ([fromRoot], [toRoot]) leave visible, a text shows whole, as on iOS.
26
+ * None: the pair doesn't fly — a text that doesn't change, or, with a line in [log], a view without a size or a
27
+ * picture that can't be taken.
33
28
  */
34
29
  fun create(
35
30
  from: View,
36
31
  to: View,
37
- toParent: View?,
38
- layer: TransitionLayer,
32
+ fromRoot: View?,
33
+ toRoot: View?,
34
+ layer: View,
39
35
  options: SharedElementTransitionOptions,
40
36
  fallbackDuration: Long,
41
37
  log: (String) -> Unit,
42
38
  ): Flight? {
43
- val flight = when {
44
- from is ReactTextView && to is ReactTextView -> pictures(
45
- TextChangeAnimator(from, to).takeIf { it.shouldAnimate() }?.create(options),
46
- )
47
- hasChildren(from) || hasChildren(to) -> pictures(
48
- ViewChangeAnimator(from, to).takeIf { it.shouldAnimate() }?.create(options),
49
- ) ?: moves(PlainViewAnimator(from, to, layer).create())
50
- from is ReactImageView && to is ReactImageView -> moves(ReactImageAnimator(from, to, layer).create())
51
- from is ImageView && to is ImageView -> moves(
52
- ImageMatrixAnimator(from, to, layer, from.parent as? View, toParent, options.toId.get(""), log)
53
- .create(),
54
- )
55
- else -> moves(PlainViewAnimator(from, to, layer).create())
56
- } ?: return null
57
- val animator = flight.animator
39
+ val name = pairName(options.fromId.get(""), options.toId.get(""))
40
+ if (from.width <= 0 || from.height <= 0 || to.width <= 0 || to.height <= 0) {
41
+ elementSkipped(name, "a view of the pair has no size, it isn't laid out", log)
42
+ return null
43
+ }
44
+ val picture = if (from is ReactTextView && to is ReactTextView) {
45
+ val text = TextMorph.of(from, to, layer) ?: return noPicture(name, log)
46
+ if (!text.changes) return null
47
+ text
48
+ } else {
49
+ val image = if (from is ImageView && to is ImageView) {
50
+ ImageMorph.of(from, to, fromRoot, toRoot, layer)
51
+ } else {
52
+ null
53
+ }
54
+ image ?: ViewMorph.of(from, to, fromRoot, toRoot, layer) ?: return noPicture(name, log)
55
+ }
56
+ val animator = MoveAnimator().apply {
57
+ element = name
58
+ onStart {
59
+ picture.shown = true
60
+ picture.update(0f, curve.getInterpolation(0f))
61
+ layer.invalidate()
62
+ }
63
+ onFrame {
64
+ picture.update(it, curve.getInterpolation(it))
65
+ layer.invalidate()
66
+ }
67
+ // A flight that landed keeps its last frame until the transition takes the layer away: the screens may
68
+ // still move. A stopped one draws nothing more.
69
+ onEnd {
70
+ if (!landed) picture.shown = false
71
+ layer.invalidate()
72
+ }
73
+ }
58
74
  val duration = AnimationRules.durationOf(options.duration.get(null), fallbackDuration)
59
75
  animator.duration = duration
60
76
  animator.startDelay = AnimationRules.delayOf(options.startDelay.get(null))
61
77
  animator.interpolator = Curves.of(options.interpolation, duration)
62
- return flight
78
+ return Flight(animator, picture)
63
79
  }
64
80
 
65
- private fun pictures(animator: Animator?): Flight? = animator?.let { Flight(it, drawsPictures = true) }
66
-
67
- private fun moves(animator: Animator?): Flight? = animator?.let { Flight(it, drawsPictures = false) }
68
-
69
- private fun hasChildren(view: View): Boolean = view is ReactViewGroup && view.childCount > 0
81
+ private fun noPicture(name: String, log: (String) -> Unit): Flight? {
82
+ elementSkipped(name, "no picture of a view of the pair can be taken", log)
83
+ return null
84
+ }
70
85
  }
@@ -0,0 +1,176 @@
1
+ package dev.apexnative.navigation.views.element.animators
2
+
3
+ import android.graphics.Canvas
4
+ import android.graphics.Picture
5
+ import android.graphics.PointF
6
+ import android.text.Layout
7
+ import android.view.View
8
+ import android.widget.TextView
9
+ import com.facebook.react.views.text.ReactTextView
10
+ import dev.apexnative.navigation.utils.TextViewUtils
11
+ import dev.apexnative.navigation.views.animations.ValueInterpolation
12
+ import kotlin.math.abs
13
+ import kotlin.math.min
14
+ import kotlin.math.roundToInt
15
+
16
+ /**
17
+ * The text moves as two pictures of itself, of the text that goes away and of the text that comes, the same text or
18
+ * another. Both keep their proportions, scaled by the font size from a point of the first line, and one turns into the
19
+ * other in a quarter of the move: at its start when the text grows, at its end when it shrinks, so the larger picture
20
+ * shows most of the way (as on iOS). Each text is where it is drawn, at the scale and angle its parents and its own
21
+ * properties give it; the angle goes along the shorter arc ([FlightGeometry]). The pictures are drawing commands, not
22
+ * pixels: they stay sharp at any scale and keep the colors, emoji and background of the text.
23
+ */
24
+ internal class TextMorph private constructor(private val start: TextPicture, private val end: TextPicture) :
25
+ FlightPicture() {
26
+ /** Whether the text changes on the way: another text, another size, or drawn elsewhere. */
27
+ val changes: Boolean
28
+ get() = start.text != end.text || start.fontSize != end.fontSize || start.drawnElsewhere(end)
29
+
30
+ private val grows = end.shownSize >= start.shownSize
31
+ private var progress = 0f
32
+ private var time = 0f
33
+ private var changeOver = 0f
34
+ private var mirrorX = 1f
35
+ private var mirrorY = 1f
36
+
37
+ override fun update(time: Float, progress: Float) {
38
+ this.progress = progress
39
+ this.time = time
40
+ val changeOverStart = if (grows) 0f else 1f - CHANGE_OVER
41
+ changeOver = ((time - changeOverStart) / CHANGE_OVER).coerceIn(0f, 1f)
42
+ }
43
+
44
+ override fun draw(canvas: Canvas) {
45
+ val x = start.position.x + (end.position.x - start.position.x) * progress
46
+ val y = start.position.y + (end.position.y - start.position.y) * progress
47
+ val fontSize = start.shownSize + (end.shownSize - start.shownSize) * progress
48
+ val rotation = ValueInterpolation.angle(start.rotation, end.rotation, progress, time)
49
+ mirrorX = ValueInterpolation.number(start.mirrorX, end.mirrorX, progress, time)
50
+ mirrorY = ValueInterpolation.number(start.mirrorY, end.mirrorY, progress, time)
51
+ draw(canvas, start, x, y, fontSize, rotation, 1f - changeOver)
52
+ draw(canvas, end, x, y, fontSize, rotation, changeOver)
53
+ }
54
+
55
+ private fun draw(
56
+ canvas: Canvas,
57
+ text: TextPicture,
58
+ x: Float,
59
+ y: Float,
60
+ fontSize: Float,
61
+ rotation: Float,
62
+ shown: Float,
63
+ ) {
64
+ val alpha = (shown * text.alpha * 255).roundToInt().coerceIn(0, 255)
65
+ if (alpha == 0) return
66
+ val scale = fontSize / text.fontSize
67
+ val count = canvas.save()
68
+ canvas.translate(x, y)
69
+ canvas.rotate(rotation)
70
+ canvas.scale(scale * mirrorX, scale * mirrorY)
71
+ canvas.translate(-text.anchor.x, -text.anchor.y)
72
+ // The picture fades as a whole: its letters and background don't show through each other.
73
+ if (alpha < 255) {
74
+ canvas.saveLayerAlpha(0f, 0f, text.picture.width.toFloat(), text.picture.height.toFloat(), alpha)
75
+ }
76
+ canvas.drawPicture(text.picture)
77
+ canvas.restoreToCount(count)
78
+ }
79
+
80
+ companion object {
81
+ private const val CHANGE_OVER = 0.25f
82
+
83
+ /**
84
+ * The morph of [from] into [to] in [layer]; none when a text isn't laid out or its picture can't be taken.
85
+ * Texts that line up the same way go from that point of their first lines (the same text lies over itself);
86
+ * others from the start of the line, as on iOS: a centered text no longer sticks out of a text at the start.
87
+ */
88
+ fun of(from: ReactTextView, to: ReactTextView, layer: View): TextMorph? {
89
+ val fromLayout = from.layout ?: return null
90
+ val toLayout = to.layout ?: return null
91
+ val edge = lineEdge(fromLayout).takeIf { it == lineEdge(toLayout) } ?: LineEdge.START
92
+ val start = TextPicture.of(from, LayerPlace.of(from, layer), edge) ?: return null
93
+ val end = TextPicture.of(to, LayerPlace.of(to, layer), edge) ?: return null
94
+ return TextMorph(start, end)
95
+ }
96
+ }
97
+ }
98
+
99
+ // A text's picture and its text, the point of its first line it is scaled from (in the view) and where that point is
100
+ // drawn in the transition layer, its font size, the scale and angle it is drawn at, and its opacity.
101
+ private class TextPicture(
102
+ val text: String,
103
+ val picture: Picture,
104
+ val anchor: PointF,
105
+ val position: PointF,
106
+ val fontSize: Float,
107
+ val scale: Float,
108
+ val rotation: Float,
109
+ val mirrorX: Float,
110
+ val mirrorY: Float,
111
+ val alpha: Float
112
+ ) {
113
+ /** The font size it shows at. */
114
+ val shownSize: Float get() = fontSize * scale
115
+
116
+ /** Whether [other] is drawn elsewhere, larger or smaller, or turned. */
117
+ fun drawnElsewhere(other: TextPicture): Boolean =
118
+ abs(position.x - other.position.x) > SAME_PLACE || abs(position.y - other.position.y) > SAME_PLACE ||
119
+ abs(scale - other.scale) > SAME_SCALE || abs(rotation - other.rotation) > SAME_ANGLE ||
120
+ mirrorX != other.mirrorX || mirrorY != other.mirrorY
121
+
122
+ companion object {
123
+ // Within half a pixel, a thousandth of the scale and a tenth of a degree: the same.
124
+ private const val SAME_PLACE = 0.5f
125
+ private const val SAME_SCALE = 0.001f
126
+ private const val SAME_ANGLE = 0.1f
127
+
128
+ fun of(view: TextView, place: LayerPlace, edge: LineEdge): TextPicture? {
129
+ val layout = view.layout ?: return null
130
+ val fontSize = TextViewUtils.getTextSize(view).takeIf { it > 0 } ?: view.textSize
131
+ if (view.width <= 0 || view.height <= 0 || layout.lineCount == 0 || fontSize <= 0) return null
132
+ // Without a picture (recording failed) the text goes to its place at once, as a different text does.
133
+ val picture = recordPicture(view) ?: return null
134
+ val anchor = PointF(
135
+ view.totalPaddingLeft + edgeX(layout, edge),
136
+ view.totalPaddingTop + layout.getLineBaseline(0).toFloat()
137
+ )
138
+ val position = place.point(anchor.x, anchor.y)
139
+ val scale = min(abs(place.scaleX), abs(place.scaleY))
140
+ return TextPicture(
141
+ view.text.toString(), picture, anchor, PointF(position[0], position[1]), fontSize, scale,
142
+ place.rotation,
143
+ mirrorX = if (place.scaleX < 0) -1f else 1f,
144
+ mirrorY = if (place.scaleY < 0) -1f else 1f,
145
+ alpha = view.alpha,
146
+ )
147
+ }
148
+
149
+ // That point of the first line, in the direction of the text.
150
+ private fun edgeX(layout: Layout, edge: LineEdge): Float {
151
+ val left = layout.getLineLeft(0)
152
+ val right = layout.getLineRight(0)
153
+ val rightToLeft = layout.getParagraphDirection(0) == Layout.DIR_RIGHT_TO_LEFT
154
+ return when (edge) {
155
+ LineEdge.CENTER -> (left + right) / 2
156
+ LineEdge.START -> if (rightToLeft) right else left
157
+ LineEdge.END -> if (rightToLeft) left else right
158
+ }
159
+ }
160
+ }
161
+ }
162
+
163
+ // Where the lines of a text line up: their start, center or end, in the direction of the text.
164
+ private enum class LineEdge { START, CENTER, END }
165
+
166
+ // ALIGN_LEFT and ALIGN_RIGHT are hidden constants, for Gravity.LEFT and RIGHT.
167
+ private fun lineEdge(layout: Layout): LineEdge {
168
+ val rightToLeft = layout.getParagraphDirection(0) == Layout.DIR_RIGHT_TO_LEFT
169
+ return when (layout.getParagraphAlignment(0).name) {
170
+ "ALIGN_CENTER" -> LineEdge.CENTER
171
+ "ALIGN_OPPOSITE" -> LineEdge.END
172
+ "ALIGN_LEFT" -> if (rightToLeft) LineEdge.END else LineEdge.START
173
+ "ALIGN_RIGHT" -> if (rightToLeft) LineEdge.START else LineEdge.END
174
+ else -> LineEdge.START
175
+ }
176
+ }
@@ -0,0 +1,108 @@
1
+ package dev.apexnative.navigation.views.element.animators
2
+
3
+ import android.graphics.Canvas
4
+ import android.graphics.Paint
5
+ import android.graphics.Picture
6
+ import android.graphics.PorterDuff
7
+ import android.graphics.PorterDuffXfermode
8
+ import android.graphics.RectF
9
+ import android.view.View
10
+ import dev.apexnative.navigation.utils.borderRadius
11
+ import kotlin.math.roundToInt
12
+
13
+ /**
14
+ * A shared view moves as two pictures of itself, as on iOS: of the view that goes away and of the one that comes, each
15
+ * with its children. The copy goes from where the one is drawn — its center, its size at the scale it is drawn at, its
16
+ * angle and corner radius — to where the other is drawn in its screen ([FlightGeometry]), the angle along the shorter
17
+ * arc; both pictures fill it, and the picture of the destination shows over the other on the way. Where a parent cuts
18
+ * a view (`overflow: hidden`, a scroll view, the screen's edge), only the part that shows flies, the mask going from
19
+ * one end's part to the other's ([FlightMask]), as on iOS. The pictures are drawing commands, taken before the views
20
+ * hide: an avatar's letter grows sharp, and what changes in the views meanwhile shows when they are back.
21
+ */
22
+ internal class ViewMorph private constructor(
23
+ private val start: ViewPicture,
24
+ private val end: ViewPicture,
25
+ ) : FlightPicture() {
26
+ private val flight = FlightGeometry(start.end, end.end)
27
+ private val cut = FlightMask.of(start.visible, end.visible)?.let(::MaskCut)
28
+ private var at = start.end
29
+ private var progress = 0f
30
+ private val rect = RectF()
31
+ private val maskPaint = Paint(Paint.ANTI_ALIAS_FLAG)
32
+ // What is drawn over the mask keeps only the mask's pixels: the corners stay smooth (a clip path on the hardware
33
+ // canvas is not anti-aliased).
34
+ private val contentPaint = Paint().apply { xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN) }
35
+
36
+ override fun update(time: Float, progress: Float) {
37
+ this.progress = progress
38
+ at = flight.at(progress, time)
39
+ cut?.update(time, progress)
40
+ }
41
+
42
+ override fun draw(canvas: Canvas) {
43
+ rect.set(-at.width / 2, -at.height / 2, at.width / 2, at.height / 2)
44
+ if (rect.isEmpty) return
45
+ val radius = lerp(start.radius, end.radius)
46
+ // The copy turns about its center, mirrored where a view is.
47
+ canvas.translate(at.centerX, at.centerY)
48
+ canvas.rotate(at.rotation)
49
+ canvas.scale(at.mirrorX, at.mirrorY)
50
+ canvas.saveLayer(rect, null)
51
+ canvas.drawRoundRect(rect, radius, radius, maskPaint)
52
+ cut?.draw(canvas, rect)
53
+ canvas.saveLayer(rect, contentPaint)
54
+ draw(canvas, start, start.alpha)
55
+ draw(canvas, end, end.alpha * progress)
56
+ }
57
+
58
+ // A picture fills the copy, as on iOS.
59
+ private fun draw(canvas: Canvas, view: ViewPicture, shown: Float) {
60
+ val alpha = (shown * 255).roundToInt().coerceIn(0, 255)
61
+ if (alpha == 0) return
62
+ val width = view.picture.width.toFloat()
63
+ val height = view.picture.height.toFloat()
64
+ val count = canvas.save()
65
+ canvas.translate(rect.left, rect.top)
66
+ canvas.scale(rect.width() / width, rect.height() / height)
67
+ // The picture fades as a whole: its children and background don't show through each other.
68
+ if (alpha < 255) canvas.saveLayerAlpha(0f, 0f, width, height, alpha)
69
+ canvas.drawPicture(view.picture)
70
+ canvas.restoreToCount(count)
71
+ }
72
+
73
+ private fun lerp(from: Float, to: Float) = from + (to - from) * progress
74
+
75
+ companion object {
76
+ /**
77
+ * The morph of [from] into [to] in [layer], each cut by its parents up to the view of its screen ([fromRoot],
78
+ * [toRoot]); none when a picture of either can't be taken.
79
+ */
80
+ fun of(from: View, to: View, fromRoot: View?, toRoot: View?, layer: View): ViewMorph? {
81
+ val start = ViewPicture.of(from, LayerPlace.of(from, layer, fromRoot)) ?: return null
82
+ val end = ViewPicture.of(to, LayerPlace.of(to, layer, toRoot)) ?: return null
83
+ return ViewMorph(start, end)
84
+ }
85
+ }
86
+ }
87
+
88
+ // A view's picture, where it is drawn in the transition layer, its corner radius there, its opacity and the part of it
89
+ // that shows.
90
+ private class ViewPicture(
91
+ val picture: Picture,
92
+ val end: FlightEnd,
93
+ val radius: Float,
94
+ val alpha: Float,
95
+ val visible: VisiblePart,
96
+ ) {
97
+ companion object {
98
+ fun of(view: View, place: LayerPlace): ViewPicture? {
99
+ if (view.width <= 0 || view.height <= 0) return null
100
+ val picture = recordPicture(view) ?: return null
101
+ val end = place.end(view.width, view.height)
102
+ val radius = view.borderRadius
103
+ return ViewPicture(
104
+ picture, end, radius * end.scale, view.alpha, place.visible(view.width, view.height, radius),
105
+ )
106
+ }
107
+ }
108
+ }
@@ -48,15 +48,24 @@ internal class SideMenuView(context: Context) : DrawerLayout(context), SideMenuM
48
48
  center.addView(content, FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT))
49
49
  }
50
50
 
51
- /** The part of [side], holding [content]: a drawer at that edge, the whole height of the side menu. */
52
- fun addPart(side: Side, content: View): FrameLayout {
51
+ /**
52
+ * The part of [side], empty until [fillPart]: a drawer at that edge, the whole height of the side menu. It opens,
53
+ * closes and takes its width and lock without its content.
54
+ */
55
+ fun addPart(side: Side): FrameLayout {
53
56
  val part = FrameLayout(context)
54
- part.addView(content, FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT))
55
57
  addView(part, LayoutParams(MATCH_PARENT, MATCH_PARENT, gravityOf(side)))
56
58
  parts[side.ordinal] = part
57
59
  return part
58
60
  }
59
61
 
62
+ /** [content] fills the part of [side], once. */
63
+ fun fillPart(side: Side, content: View) {
64
+ val part = partOf(side) ?: return
65
+ if (content.parent === part) return
66
+ part.addView(content, FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT))
67
+ }
68
+
60
69
  /** The part of [side]; none when the layout has no menu there. */
61
70
  fun partOf(side: Side): FrameLayout? = parts[side.ordinal]
62
71
 
@@ -0,0 +1,45 @@
1
+ package dev.apexnative.navigation.views.stack
2
+
3
+ import android.graphics.Bitmap
4
+ import android.graphics.Canvas
5
+ import android.graphics.drawable.BitmapDrawable
6
+ import android.graphics.drawable.Drawable
7
+ import android.view.View
8
+
9
+ /**
10
+ * What fills the room beside a moving screen in a transition (`StackLayout.extendEdge`), where the system's
11
+ * transitions between activities stretch a window's edge (`<extend>` of `activity_open_*` and `activity_close_*`): the
12
+ * column of pixels at the screen's edge, stretched across the room, as the system stretches the window's. What the
13
+ * screen shows there goes on beside it — a gradient its content draws, not only its own background. Taken at the start
14
+ * of every push and pop. Main thread only.
15
+ */
16
+ internal object ScreenEdge {
17
+ /**
18
+ * The column of pixels at [view]'s left edge ([left]) or right edge, made to be stretched; its background when the
19
+ * screen isn't laid out as it shows ([laidOut]: not after a rotation while it was out of the stack) or can't be drawn
20
+ * in software (a `HARDWARE` bitmap in it, a view that fails to draw), none without one either.
21
+ */
22
+ fun pictureOf(view: View, left: Boolean, laidOut: Boolean): Drawable? =
23
+ (if (laidOut) columnOf(view, left) else null) ?: backgroundOf(view)
24
+
25
+ // One pixel wide and as tall as the screen: the view draws itself into a canvas that keeps that column only. Any
26
+ // view of the screen may fail to draw in software (a hardware bitmap, a view that wants a hardware canvas): the
27
+ // screen's background stands in then, as the transition must go on.
28
+ private fun columnOf(view: View, left: Boolean): Drawable? {
29
+ val width = view.width
30
+ val height = view.height
31
+ if (width <= 0 || height <= 0) return null
32
+ return try {
33
+ val column = Bitmap.createBitmap(1, height, Bitmap.Config.ARGB_8888)
34
+ val canvas = Canvas(column)
35
+ if (!left) canvas.translate(-(width - 1).toFloat(), 0f)
36
+ view.draw(canvas)
37
+ BitmapDrawable(view.resources, column)
38
+ } catch (e: RuntimeException) {
39
+ null
40
+ }
41
+ }
42
+
43
+ private fun backgroundOf(view: View): Drawable? =
44
+ view.background?.constantState?.newDrawable(view.resources)?.mutate()
45
+ }
@@ -2,6 +2,8 @@ package dev.apexnative.navigation.views.stack
2
2
 
3
3
  import android.annotation.SuppressLint
4
4
  import android.content.Context
5
+ import android.graphics.Canvas
6
+ import android.graphics.drawable.Drawable
5
7
  import android.view.Gravity
6
8
  import android.view.View
7
9
  import android.view.ViewGroup
@@ -18,7 +20,8 @@ import java.util.WeakHashMap
18
20
  * moves between its places without leaving it, so it doesn't leave and join the window again; a covered screen that
19
21
  * comes back gets the last window insets the stack got before it joins, and nothing asks the window to send them again
20
22
  * (CoordinatorLayout asks for insets only as it joins the window itself and only with `fitsSystemWindows`, which this
21
- * view doesn't set). Main thread only.
23
+ * view doesn't set). In a transition of the stack's own the bar is drawn with the screen it goes with
24
+ * ([barTravels]). Main thread only.
22
25
  */
23
26
  @SuppressLint("ViewConstructor")
24
27
  class StackLayout(context: Context) : CoordinatorLayout(context) {
@@ -134,4 +137,140 @@ class StackLayout(context: Context) : CoordinatorLayout(context) {
134
137
  requestLayout()
135
138
  invalidate()
136
139
  }
140
+
141
+ // The edges of the screens in a transition: drawn beside each, under it, where it moves and as transparent as it.
142
+ private val edges = HashMap<View, Edge>()
143
+
144
+ private class Edge(val picture: Drawable, val width: Int, val atStart: Boolean)
145
+
146
+ /**
147
+ * [view] extends its start edge ([atStart]) or its end edge by [width] pixels while it moves, as the system's
148
+ * transitions between activities extend a window: the pixels at its edge, stretched, fill the room it moves away
149
+ * from, so the screen under it never shows at its edge. [dropEdge] ends it. Each frame of the move calls
150
+ * [edgesMoved].
151
+ */
152
+ fun extendEdge(view: View, atStart: Boolean, width: Int) {
153
+ val left = atStart != (layoutDirection == LAYOUT_DIRECTION_RTL)
154
+ // A screen put back for a pop keeps the size of its last layout until the next one: after a rotation while it was
155
+ // out of the stack, its pixels are of another width.
156
+ val picture = ScreenEdge.pictureOf(view, left, laidOut = view.width == this.width) ?: return
157
+ edges[view] = Edge(picture, width, left)
158
+ invalidate()
159
+ }
160
+
161
+ /** [view] moves no more: its edge goes. */
162
+ fun dropEdge(view: View) {
163
+ if (edges.remove(view) != null) invalidate()
164
+ }
165
+
166
+ /** A screen with an extended edge moved: the edges are drawn again where the screens are now. */
167
+ fun edgesMoved() {
168
+ if (edges.isNotEmpty()) invalidate()
169
+ }
170
+
171
+ // The bar's travel in a transition of the stack's own: the screen the bar goes with, the screen that leaves with the
172
+ // picture of the bar as it was, and whether that one lies over the bar (a pop).
173
+ private var barScreen: View? = null
174
+ private var barLeaving: View? = null
175
+ private var barPicture: Drawable? = null
176
+ private var leavingOver = false
177
+
178
+ /**
179
+ * The bar goes with [screen] in a transition of the stack's own: it is drawn as [screen] moves (its translation,
180
+ * scale and rotation around its pivot, its alpha). [picture], laid where the bar is, goes the same way with
181
+ * [leaving]: it is drawn right over that screen, outside its bounds too (a screen laid out under the bar). With
182
+ * [over] the leaving screen and its picture lie over the bar (a pop), else under it. Only the drawing moves: the
183
+ * bar's views and touches stay in place. [endBarTravel] ends it.
184
+ */
185
+ fun barTravels(screen: View, leaving: View?, picture: Drawable?, over: Boolean) {
186
+ barScreen = screen
187
+ barLeaving = leaving
188
+ barPicture = picture
189
+ leavingOver = over && leaving != null
190
+ invalidate()
191
+ }
192
+
193
+ /** The bar is drawn in its place again, over the screens; the picture goes. */
194
+ fun endBarTravel() {
195
+ if (barScreen == null) return
196
+ barScreen = null
197
+ barLeaving = null
198
+ barPicture = null
199
+ leavingOver = false
200
+ invalidate()
201
+ }
202
+
203
+ override fun dispatchDraw(canvas: Canvas) {
204
+ super.dispatchDraw(canvas)
205
+ // The screens' animators change only their own properties, which don't draw this view again: each frame of
206
+ // the bar's travel asks for the next.
207
+ if (barScreen != null) postInvalidateOnAnimation()
208
+ }
209
+
210
+ override fun drawChild(canvas: Canvas, child: View, drawingTime: Long): Boolean {
211
+ edges[child]?.let { drawEdge(canvas, child, it) }
212
+ val screen = barScreen ?: return super.drawChild(canvas, child, drawingTime)
213
+ // The leaving screen, while it is still here, and its picture; on a pop the bar right under them.
214
+ val leaving = barLeaving?.takeIf(::holds)
215
+ val under = leaving.takeIf { leavingOver }
216
+ if (child === topBar) {
217
+ if (under != null) return false
218
+ return drawWith(canvas, screen, topBar.left.toFloat(), topBar.top + topBar.translationY,
219
+ topBar.right.toFloat(), topBar.bottom + topBar.translationY) {
220
+ super.drawChild(canvas, topBar, drawingTime)
221
+ }
222
+ }
223
+ if (child === under && topBar.visibility == VISIBLE) {
224
+ drawWith(canvas, screen, topBar.left.toFloat(), topBar.top + topBar.translationY,
225
+ topBar.right.toFloat(), topBar.bottom + topBar.translationY) {
226
+ super.drawChild(canvas, topBar, drawingTime)
227
+ }
228
+ }
229
+ val drawn = super.drawChild(canvas, child, drawingTime)
230
+ val picture = barPicture
231
+ if (child === leaving && picture != null) {
232
+ val bounds = picture.bounds
233
+ drawWith(canvas, child, bounds.left.toFloat(), bounds.top.toFloat(), bounds.right.toFloat(),
234
+ bounds.bottom.toFloat()) {
235
+ picture.draw(canvas)
236
+ false
237
+ }
238
+ }
239
+ return drawn
240
+ }
241
+
242
+ // Draws with [screen]'s transform and alpha what [draw] draws within the bounds given, in this view's coordinates.
243
+ private fun drawWith(
244
+ canvas: Canvas,
245
+ screen: View,
246
+ left: Float,
247
+ top: Float,
248
+ right: Float,
249
+ bottom: Float,
250
+ draw: () -> Boolean,
251
+ ): Boolean {
252
+ val alpha = if (screen.visibility == VISIBLE) screen.alpha else 0f
253
+ if (alpha <= 0f) return false
254
+ val saved = canvas.save()
255
+ canvas.translate(screen.left.toFloat(), screen.top.toFloat())
256
+ canvas.concat(screen.matrix)
257
+ canvas.translate(-screen.left.toFloat(), -screen.top.toFloat())
258
+ if (alpha < 1f) canvas.saveLayerAlpha(left, top, right, bottom, (alpha * 255).toInt())
259
+ val drawn = draw()
260
+ canvas.restoreToCount(saved)
261
+ return drawn
262
+ }
263
+
264
+ // At the child's place to the fraction of a pixel, as its own translation draws it, and one pixel under it: no seam
265
+ // of the screen below shows between them.
266
+ private fun drawEdge(canvas: Canvas, child: View, edge: Edge) {
267
+ if (child.visibility != VISIBLE || child.alpha <= 0f) return
268
+ val x = if (edge.atStart) child.left + child.translationX - edge.width else child.right + child.translationX - 1f
269
+ val saved = canvas.save()
270
+ canvas.translate(x, child.top + child.translationY)
271
+ edge.picture.setBounds(0, 0, edge.width + 1, child.height)
272
+ edge.picture.alpha = (child.alpha * 255).toInt()
273
+ edge.picture.draw(canvas)
274
+ canvas.restoreToCount(saved)
275
+ }
137
276
  }