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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (573) hide show
  1. package/ApexNavigation.podspec +2 -1
  2. package/CHANGELOG.md +120 -0
  3. package/README.md +147 -51
  4. package/android/CLAUDE.md +78 -25
  5. package/android/CORE.md +49 -25
  6. package/android/RECIPES.md +13 -6
  7. package/android/consumer-rules.pro +6 -0
  8. package/android/src/main/java/dev/apexnative/navigation/NavigationActivity.kt +85 -10
  9. package/android/src/main/java/dev/apexnative/navigation/NavigationApplication.kt +34 -13
  10. package/android/src/main/java/dev/apexnative/navigation/layout/LayoutChecks.kt +5 -1
  11. package/android/src/main/java/dev/apexnative/navigation/layout/LayoutNode.kt +6 -2
  12. package/android/src/main/java/dev/apexnative/navigation/nativescreen/NativeScreenContext.kt +2 -2
  13. package/android/src/main/java/dev/apexnative/navigation/options/AnimationsOptions.kt +2 -2
  14. package/android/src/main/java/dev/apexnative/navigation/options/BottomTabOptions.kt +1 -1
  15. package/android/src/main/java/dev/apexnative/navigation/options/BottomTabsOptions.kt +13 -8
  16. package/android/src/main/java/dev/apexnative/navigation/options/ButtonMenuOptions.kt +2 -2
  17. package/android/src/main/java/dev/apexnative/navigation/options/ButtonOptions.kt +3 -3
  18. package/android/src/main/java/dev/apexnative/navigation/options/HardwareBackButtonOptions.kt +9 -1
  19. package/android/src/main/java/dev/apexnative/navigation/options/LargeTitleOptions.kt +1 -1
  20. package/android/src/main/java/dev/apexnative/navigation/options/LayoutAnimation.kt +1 -1
  21. package/android/src/main/java/dev/apexnative/navigation/options/OptionKey.kt +18 -0
  22. package/android/src/main/java/dev/apexnative/navigation/options/OptionPaths.kt +91 -0
  23. package/android/src/main/java/dev/apexnative/navigation/options/OptionsCache.kt +8 -4
  24. package/android/src/main/java/dev/apexnative/navigation/options/SheetOptions.kt +7 -4
  25. package/android/src/main/java/dev/apexnative/navigation/options/SideMenuOptions.kt +6 -1
  26. package/android/src/main/java/dev/apexnative/navigation/options/StackAnimationOptions.kt +40 -2
  27. package/android/src/main/java/dev/apexnative/navigation/options/StatusBarOptions.kt +7 -3
  28. package/android/src/main/java/dev/apexnative/navigation/options/TitleOptions.kt +2 -2
  29. package/android/src/main/java/dev/apexnative/navigation/options/TopBarAppearanceOptions.kt +1 -1
  30. package/android/src/main/java/dev/apexnative/navigation/options/TopBarOptions.kt +16 -7
  31. package/android/src/main/java/dev/apexnative/navigation/options/UserChoices.kt +159 -0
  32. package/android/src/main/java/dev/apexnative/navigation/react/CommandAnswer.kt +29 -36
  33. package/android/src/main/java/dev/apexnative/navigation/react/CommandContract.kt +59 -0
  34. package/android/src/main/java/dev/apexnative/navigation/react/ContentHeights.kt +95 -0
  35. package/android/src/main/java/dev/apexnative/navigation/react/ContentMounts.kt +66 -0
  36. package/android/src/main/java/dev/apexnative/navigation/react/ErrorTexts.kt +75 -60
  37. package/android/src/main/java/dev/apexnative/navigation/react/Hinge.kt +35 -23
  38. package/android/src/main/java/dev/apexnative/navigation/react/NavigationTurboModule.kt +12 -7
  39. package/android/src/main/java/dev/apexnative/navigation/react/OptionsCommands.kt +42 -4
  40. package/android/src/main/java/dev/apexnative/navigation/react/PendingCalls.kt +48 -0
  41. package/android/src/main/java/dev/apexnative/navigation/react/ReactView.kt +54 -20
  42. package/android/src/main/java/dev/apexnative/navigation/react/ReloadCoordinator.kt +7 -6
  43. package/android/src/main/java/dev/apexnative/navigation/react/ScreenEnvironment.kt +177 -0
  44. package/android/src/main/java/dev/apexnative/navigation/react/ScreenRegions.kt +19 -50
  45. package/android/src/main/java/dev/apexnative/navigation/react/ScrollEvents.kt +49 -128
  46. package/android/src/main/java/dev/apexnative/navigation/react/events/AppearanceDispatcher.kt +50 -81
  47. package/android/src/main/java/dev/apexnative/navigation/react/events/EventContract.kt +226 -0
  48. package/android/src/main/java/dev/apexnative/navigation/react/events/EventEmitter.kt +135 -94
  49. package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationState.kt +154 -0
  50. package/android/src/main/java/dev/apexnative/navigation/react/events/ScreenAppearance.kt +0 -6
  51. package/android/src/main/java/dev/apexnative/navigation/safearea/SafeAreaView.kt +12 -10
  52. package/android/src/main/java/dev/apexnative/navigation/slots/SlotContainers.kt +10 -7
  53. package/android/src/main/java/dev/apexnative/navigation/slots/SlotScreenView.kt +39 -19
  54. package/android/src/main/java/dev/apexnative/navigation/slots/SlotView.kt +16 -4
  55. package/android/src/main/java/dev/apexnative/navigation/slots/SlotViews.kt +40 -0
  56. package/android/src/main/java/dev/apexnative/navigation/utils/ImageKey.kt +66 -0
  57. package/android/src/main/java/dev/apexnative/navigation/utils/ImageLoader.kt +7 -89
  58. package/android/src/main/java/dev/apexnative/navigation/utils/ImageRequests.kt +76 -0
  59. package/android/src/main/java/dev/apexnative/navigation/utils/MaterialTheme.kt +5 -6
  60. package/android/src/main/java/dev/apexnative/navigation/utils/OptionImages.kt +262 -0
  61. package/android/src/main/java/dev/apexnative/navigation/utils/SystemAnimations.kt +36 -0
  62. package/android/src/main/java/dev/apexnative/navigation/utils/UiUtils.kt +3 -3
  63. package/android/src/main/java/dev/apexnative/navigation/utils/ViewController.kt +3 -1
  64. package/android/src/main/java/dev/apexnative/navigation/utils/ViewExtensions.kt +0 -13
  65. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementController.kt +10 -7
  66. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/SecondaryScreenPresenter.kt +13 -5
  67. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/AppliedTabCalls.kt +49 -0
  68. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsCollapseBehavior.kt +5 -3
  69. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsController.kt +108 -34
  70. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsPresenter.kt +25 -24
  71. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowGeometry.kt +22 -0
  72. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabItems.kt +3 -3
  73. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabsRoom.kt +0 -5
  74. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentPresenter.kt +28 -7
  75. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentViewController.kt +12 -9
  76. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ContentReadiness.kt +2 -2
  77. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/RenderWait.kt +27 -7
  78. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenFrame.kt +1 -1
  79. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenReadiness.kt +103 -56
  80. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenSafeArea.kt +29 -11
  81. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/externalcomponent/ExternalComponentViewController.kt +2 -6
  82. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalAnimations.kt +22 -24
  83. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalCoordinator.kt +109 -21
  84. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalRecord.kt +21 -6
  85. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalSheet.kt +476 -73
  86. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalViews.kt +57 -25
  87. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetBack.kt +42 -0
  88. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetStops.kt +83 -0
  89. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackCheck.kt +50 -0
  90. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackState.kt +49 -14
  91. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/Navigator.kt +71 -12
  92. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/RootCoordinator.kt +37 -11
  93. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/overlay/OverlayCoordinator.kt +10 -8
  94. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/Capabilities.kt +11 -4
  95. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ContainerBackground.kt +3 -3
  96. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ParentController.kt +6 -6
  97. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuController.kt +42 -9
  98. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuMotion.kt +19 -8
  99. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuPresenter.kt +16 -7
  100. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuRules.kt +43 -4
  101. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitPanes.kt +23 -0
  102. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitViewController.kt +77 -17
  103. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/BackPreview.kt +315 -0
  104. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/PreparedFrame.kt +3 -3
  105. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackCommands.kt +30 -20
  106. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackController.kt +216 -18
  107. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackDisplay.kt +26 -1
  108. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackQueue.kt +149 -41
  109. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackTransitions.kt +26 -8
  110. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackViews.kt +115 -6
  111. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabMotion.kt +142 -0
  112. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabPresenter.kt +222 -48
  113. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/ScreenSearch.kt +3 -5
  114. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/StackSearchPresenter.kt +30 -34
  115. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarComponents.kt +5 -51
  116. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarRowTransition.kt +3 -2
  117. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/ButtonPlaces.kt +11 -5
  118. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/MenuChecks.kt +13 -56
  119. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarPresenter.kt +219 -54
  120. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarVisibility.kt +9 -2
  121. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ScrollEventListener.kt +6 -9
  122. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ViewController.kt +75 -21
  123. package/android/src/main/java/dev/apexnative/navigation/views/animations/AnimationLayer.kt +73 -0
  124. package/android/src/main/java/dev/apexnative/navigation/views/animations/Curves.kt +29 -11
  125. package/android/src/main/java/dev/apexnative/navigation/views/animations/ValueInterpolation.kt +14 -0
  126. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabs.kt +9 -7
  127. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabsLayout.kt +61 -2
  128. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomBottomTabItemView.kt +0 -5
  129. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomTabRow.kt +72 -10
  130. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStep.kt +31 -0
  131. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementTransitions.kt +143 -135
  132. package/android/src/main/java/dev/apexnative/navigation/views/element/TargetsWait.kt +13 -5
  133. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionLayer.kt +37 -112
  134. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionTargets.kt +9 -6
  135. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionViews.kt +100 -0
  136. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ElementPictures.kt +112 -4
  137. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/FlightGeometry.kt +346 -36
  138. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMorph.kt +199 -0
  139. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/SharedAnimatorFactory.kt +56 -41
  140. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextMorph.kt +176 -0
  141. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewMorph.kt +108 -0
  142. package/android/src/main/java/dev/apexnative/navigation/views/sidemenu/SideMenuView.kt +12 -3
  143. package/android/src/main/java/dev/apexnative/navigation/views/stack/ScreenEdge.kt +45 -0
  144. package/android/src/main/java/dev/apexnative/navigation/views/stack/StackLayout.kt +140 -1
  145. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/Fab.kt +14 -10
  146. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabCopy.kt +85 -0
  147. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabMenu.kt +13 -0
  148. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TitleBar.kt +5 -17
  149. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TopBar.kt +73 -34
  150. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonComponentCell.kt +6 -6
  151. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonView.kt +113 -0
  152. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarMenu.kt +219 -0
  153. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonBar.kt +125 -178
  154. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonMenus.kt +34 -64
  155. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonRow.kt +216 -0
  156. package/android/src/main/jni/ANNContentHeights.cpp +82 -0
  157. package/android/src/main/res/drawable/apex_navigation_ic_arrow_right.xml +14 -0
  158. package/android/src/main/res/layout/apex_navigation_menu_header.xml +19 -0
  159. package/android/src/main/res/layout/apex_navigation_menu_item.xml +68 -0
  160. package/android/src/main/res/values/styles.xml +1 -1
  161. package/android/src/main/res/values-night/styles.xml +1 -1
  162. package/cli/app.js +1 -1
  163. package/cli/doctor/checks/app.js +77 -14
  164. package/cli/doctor/checks/splash.js +4 -22
  165. package/cli/migrate/native.js +18 -0
  166. package/cli/project.js +10 -2
  167. package/cli/setup/index.js +18 -0
  168. package/cli/setup/source.js +2 -1
  169. package/cli/setup/steps/appDelegate.js +66 -11
  170. package/cli/setup/steps/mainApplication.js +134 -19
  171. package/cli/setup/steps/metro.js +46 -0
  172. package/cli/setup/steps/sceneDelegate.js +108 -0
  173. package/cli/splash/index.js +3 -1
  174. package/docs-md/architecture/native-screens.md +4 -0
  175. package/docs-md/architecture/theme-and-context.md +131 -12
  176. package/docs-md/architecture/transitions.md +58 -12
  177. package/docs-md/containers/modals.md +8 -4
  178. package/docs-md/containers/overlays.md +3 -1
  179. package/docs-md/containers/side-menu.md +19 -2
  180. package/docs-md/containers/tabs.md +5 -1
  181. package/docs-md/flows/bottom-sheets.md +4 -2
  182. package/docs-md/flows/forms-in-a-modal.md +1 -1
  183. package/docs-md/fundamentals/screens-and-props.md +9 -1
  184. package/docs-md/fundamentals/starting-the-app.md +1 -1
  185. package/docs-md/guides/cli.md +4 -3
  186. package/docs-md/guides/deep-links.md +15 -33
  187. package/docs-md/help/glossary.md +4 -4
  188. package/docs-md/help/troubleshooting.md +44 -6
  189. package/docs-md/index.json +57 -1
  190. package/docs-md/migration/from-expo-router.md +1 -1
  191. package/docs-md/migration/from-react-native-navigation.md +9 -3
  192. package/docs-md/migration/from-react-navigation.md +2 -2
  193. package/docs-md/screen-ui/back-and-gestures.md +46 -2
  194. package/docs-md/screen-ui/bar-buttons.md +5 -5
  195. package/docs-md/screen-ui/search.md +1 -1
  196. package/docs-md/screen-ui/system-ui.md +17 -12
  197. package/docs-md/screen-ui/toolbar-and-fab.md +4 -2
  198. package/docs-md/screen-ui/top-bar.md +8 -4
  199. package/docs-md/start/installation.md +21 -3
  200. package/ios/Animations/ANNFrameDriver.h +55 -15
  201. package/ios/Animations/ANNFrameDriver.mm +216 -60
  202. package/ios/Animations/ANNTransitionAnimator.h +26 -5
  203. package/ios/Animations/ANNTransitionAnimator.mm +61 -13
  204. package/ios/Animations/ANNTransitionPlan.h +2 -2
  205. package/ios/Animations/ANNTransitionPlan.mm +10 -0
  206. package/ios/Animations/ANNTransitionWait.mm +6 -7
  207. package/ios/Animations/Elements/ANNElementFinder.h +57 -0
  208. package/ios/Animations/Elements/ANNElementFinder.mm +174 -2
  209. package/ios/Animations/Elements/ANNElementTransition.h +10 -8
  210. package/ios/Animations/Elements/ANNElementTransition.mm +19 -21
  211. package/ios/Animations/Elements/ANNSharedElementFlight.h +16 -11
  212. package/ios/Animations/Elements/ANNSharedElementFlight.mm +308 -69
  213. package/ios/Animations/Interpolators/ANNInterpolate.h +2 -30
  214. package/ios/Animations/Interpolators/ANNTransformParts.h +48 -0
  215. package/ios/Animations/Interpolators/ANNTransformParts.mm +507 -0
  216. package/ios/Animations/Interpolators/ANNViewTracks.h +9 -6
  217. package/ios/Animations/Interpolators/ANNViewTracks.mm +100 -30
  218. package/ios/CLAUDE.md +60 -24
  219. package/ios/CORE.md +44 -34
  220. package/ios/Contract/ANNCommandAnswer.h +13 -5
  221. package/ios/Contract/ANNCommandAnswer.mm +40 -32
  222. package/ios/Contract/ANNCommandContract.h +15 -0
  223. package/ios/Contract/ANNCommandContract.mm +78 -0
  224. package/ios/Contract/ANNCommandRunner.h +10 -9
  225. package/ios/Contract/ANNCommandRunner.mm +22 -28
  226. package/ios/Contract/ANNErrorTexts.h +6 -2
  227. package/ios/Contract/ANNErrorTexts.mm +18 -10
  228. package/ios/Contract/ANNLayoutNode.h +3 -3
  229. package/ios/Contract/ANNLayoutReader.h +3 -3
  230. package/ios/Core/ANNAppDelegate.mm +0 -2
  231. package/ios/Core/ANNAppearanceDispatcher.h +5 -4
  232. package/ios/Core/ANNAppearanceDispatcher.mm +12 -1
  233. package/ios/Core/ANNDeepLinkQueue.h +22 -2
  234. package/ios/Core/ANNDeepLinkQueue.mm +121 -14
  235. package/ios/Core/ANNErrorHandler.h +9 -4
  236. package/ios/Core/ANNErrorHandler.mm +20 -2
  237. package/ios/Core/ANNEventContract.h +246 -0
  238. package/ios/Core/ANNEventContract.mm +225 -0
  239. package/ios/Core/ANNEventEmitter.h +6 -2
  240. package/ios/Core/ANNEventEmitter.mm +117 -80
  241. package/ios/Core/ANNHinge.h +6 -0
  242. package/ios/Core/ANNHinge.mm +15 -4
  243. package/ios/Core/ANNJavaScriptCalls.h +33 -0
  244. package/ios/Core/ANNJavaScriptCalls.mm +52 -0
  245. package/ios/Core/ANNLayoutProtocol.h +5 -5
  246. package/ios/Core/ANNNavigationState.h +7 -5
  247. package/ios/Core/ANNNavigationState.mm +8 -7
  248. package/ios/Core/ANNNodeHelper.h +32 -12
  249. package/ios/Core/ANNNodeHelper.mm +100 -3
  250. package/ios/Core/ANNParking.h +5 -4
  251. package/ios/Core/ANNReloadCoordinator.mm +5 -12
  252. package/ios/Core/ANNRenderWait.h +20 -6
  253. package/ios/Core/ANNRenderWait.mm +143 -56
  254. package/ios/Core/ANNSceneDelegate.mm +25 -15
  255. package/ios/Core/ANNSystemUI.h +3 -2
  256. package/ios/Core/ANNSystemUI.mm +7 -0
  257. package/ios/Core/ANNUtils.h +7 -0
  258. package/ios/Core/ANNUtils.mm +10 -0
  259. package/ios/Core/ApexNavigation+Internal.h +1 -1
  260. package/ios/Core/ApexNavigation.mm +7 -6
  261. package/ios/Core/UIViewController+LayoutProtocol.h +9 -2
  262. package/ios/Core/UIViewController+LayoutProtocol.mm +8 -0
  263. package/ios/Layouts/Arrangement/ANNArrangementState.h +2 -17
  264. package/ios/Layouts/Arrangement/ANNArrangementState.mm +0 -38
  265. package/ios/Layouts/Arrangement/ANNArrangementViewController.mm +10 -8
  266. package/ios/Layouts/Modal/ANNModalCoordinator.h +1 -1
  267. package/ios/Layouts/Modal/ANNModalCoordinator.mm +57 -16
  268. package/ios/Layouts/Modal/ANNModalPresentation.h +8 -5
  269. package/ios/Layouts/Modal/ANNModalPresentation.mm +12 -12
  270. package/ios/Layouts/Modal/ANNSheetPresenter.mm +83 -1
  271. package/ios/Layouts/Overlay/ANNOverlayCoordinator.mm +2 -8
  272. package/ios/Layouts/Root/ANNRootCoordinator.mm +58 -19
  273. package/ios/Layouts/Root/ANNSplashViewController.h +5 -3
  274. package/ios/Layouts/Root/ANNSplashViewController.mm +147 -0
  275. package/ios/Layouts/Screen/ANNComponentPresenter.h +11 -3
  276. package/ios/Layouts/Screen/ANNComponentPresenter.mm +34 -6
  277. package/ios/Layouts/Screen/ANNComponentViewController.h +15 -13
  278. package/ios/Layouts/Screen/ANNComponentViewController.mm +130 -75
  279. package/ios/Layouts/Screen/ANNNativeScreenContext.mm +7 -5
  280. package/ios/Layouts/Screen/ANNPreviewInteraction.h +7 -4
  281. package/ios/Layouts/Screen/ANNPreviewInteraction.mm +72 -10
  282. package/ios/Layouts/Screen/ANNScreenEnvironment.h +63 -0
  283. package/ios/Layouts/Screen/ANNScreenEnvironment.mm +181 -0
  284. package/ios/Layouts/Screen/ANNScreenPlace.h +53 -0
  285. package/ios/Layouts/Screen/ANNScreenPlace.mm +205 -0
  286. package/ios/Layouts/Screen/ANNScreenRegions.h +3 -18
  287. package/ios/Layouts/Screen/ANNScreenRegions.mm +9 -44
  288. package/ios/Layouts/Screen/ANNScreenSafeArea.h +4 -9
  289. package/ios/Layouts/Screen/ANNScreenSafeArea.mm +14 -16
  290. package/ios/Layouts/Screen/ANNScreenSettling.h +32 -0
  291. package/ios/Layouts/Screen/ANNScreenSettling.mm +137 -0
  292. package/ios/Layouts/SideMenu/ANNSideMenuTypes.h +8 -0
  293. package/ios/Layouts/SideMenu/ANNSideMenuViewController.mm +83 -14
  294. package/ios/Layouts/SplitView/ANNSplitViewCommands.h +3 -2
  295. package/ios/Layouts/SplitView/ANNSplitViewCommands.mm +105 -39
  296. package/ios/Layouts/SplitView/ANNSplitViewController.mm +7 -8
  297. package/ios/Layouts/Stack/ANNPreviewPush.h +7 -6
  298. package/ios/Layouts/Stack/ANNPreviewPush.mm +142 -27
  299. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.h +11 -2
  300. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.mm +14 -7
  301. package/ios/Layouts/Stack/ANNStackCommands.mm +1 -0
  302. package/ios/Layouts/Stack/ANNStackController.h +8 -0
  303. package/ios/Layouts/Stack/ANNStackController.mm +184 -16
  304. package/ios/Layouts/Stack/ANNStackQueue.h +5 -2
  305. package/ios/Layouts/Stack/ANNStackQueue.mm +56 -43
  306. package/ios/Layouts/Stack/ANNSwipePopInteraction.h +26 -0
  307. package/ios/Layouts/Stack/ANNSwipePopInteraction.mm +185 -0
  308. package/ios/Layouts/Stack/InteractivePopGestureDelegate.mm +28 -4
  309. package/ios/Layouts/Stack/UINavigationController+ANNCommands.h +4 -2
  310. package/ios/Layouts/Stack/UINavigationController+ANNCommands.mm +2 -3
  311. package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.h +4 -0
  312. package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.mm +11 -0
  313. package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.h +12 -1
  314. package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.mm +23 -0
  315. package/ios/Layouts/Tabs/ANNBottomTabsController.h +3 -0
  316. package/ios/Layouts/Tabs/ANNBottomTabsController.mm +237 -57
  317. package/ios/Layouts/Tabs/ANNBottomTabsCustomRow.mm +8 -3
  318. package/ios/Layouts/Tabs/ANNBottomTabsPresenter.h +6 -2
  319. package/ios/Layouts/Tabs/ANNBottomTabsPresenter.mm +232 -43
  320. package/ios/Layouts/Tabs/ANNTabsDesign.h +6 -5
  321. package/ios/Layouts/Tabs/ANNTabsDesign.mm +9 -1
  322. package/ios/Layouts/Tabs/UITabBar+utils.h +5 -5
  323. package/ios/Layouts/Tabs/UITabBar+utils.mm +32 -13
  324. package/ios/Options/ANNAnimationOptions.h +2 -1
  325. package/ios/Options/ANNAnimationOptions.mm +1 -1
  326. package/ios/Options/ANNBottomTabsOptions.h +2 -0
  327. package/ios/Options/ANNBottomTabsOptions.mm +1 -0
  328. package/ios/Options/ANNOptions.h +25 -0
  329. package/ios/Options/ANNOptions.mm +157 -1
  330. package/ios/Options/ANNOptionsCache.h +7 -6
  331. package/ios/Options/ANNOptionsReader.mm +108 -0
  332. package/ios/Options/ANNSearchBarOptions.h +4 -3
  333. package/ios/Options/ANNSheetOptions.h +4 -1
  334. package/ios/Options/ANNSideMenuOptions.h +2 -0
  335. package/ios/Options/ANNSideMenuOptions.mm +2 -0
  336. package/ios/Options/ANNStackPopAnimationOptions.h +13 -0
  337. package/ios/Options/ANNStackPopAnimationOptions.mm +11 -0
  338. package/ios/Options/ANNUserChoice.h +57 -0
  339. package/ios/Options/ANNUserChoice.mm +44 -0
  340. package/ios/Options/Params/ANNImageSource.h +61 -0
  341. package/ios/Options/Params/ANNImageSource.mm +101 -0
  342. package/ios/Options/Params/ANNOptionImages.h +37 -0
  343. package/ios/Options/Params/ANNOptionImages.mm +284 -0
  344. package/ios/Options/Params/ANNParam.h +15 -0
  345. package/ios/Options/Params/ANNParam.mm +61 -0
  346. package/ios/Options/Params/Color.h +3 -0
  347. package/ios/Options/Params/Color.mm +21 -0
  348. package/ios/Options/Params/ColorParser.h +4 -3
  349. package/ios/Options/Params/ColorParser.mm +22 -4
  350. package/ios/Options/Params/Image.h +15 -2
  351. package/ios/Options/Params/Image.mm +35 -2
  352. package/ios/Options/Params/ImageParser.h +5 -5
  353. package/ios/Options/Params/ImageParser.mm +28 -46
  354. package/ios/Public/ApexNavigation/ANNSceneDelegate.h +3 -0
  355. package/ios/Public/ApexNavigation/ApexNavigation.h +1 -1
  356. package/ios/RECIPES.md +13 -6
  357. package/ios/React/ANNReactView.mm +6 -25
  358. package/ios/React/ANNSafeAreaViewComponentView.mm +28 -17
  359. package/ios/React/ANNSurfaceHostingView.h +14 -0
  360. package/ios/React/ANNSurfaceHostingView.mm +144 -1
  361. package/ios/React/Slots/ANNSlotComponentView.mm +24 -17
  362. package/ios/React/Slots/ANNSlotContainers.h +14 -6
  363. package/ios/React/Slots/ANNSlotContainers.mm +75 -2
  364. package/ios/React/Slots/ANNSlotHost.mm +1 -3
  365. package/ios/React/Slots/ANNSlotScreenView.mm +8 -2
  366. package/ios/TopBar/ANNBackButtonPresenter.mm +6 -5
  367. package/ios/TopBar/ANNBarAppearance.h +2 -1
  368. package/ios/TopBar/ANNBarAppearance.mm +111 -30
  369. package/ios/TopBar/ANNBarBackgroundComponent.mm +16 -0
  370. package/ios/TopBar/ANNBarButtonComponentView.h +4 -4
  371. package/ios/TopBar/ANNBarButtonComponentView.mm +1 -1
  372. package/ios/TopBar/ANNBarButtons.h +14 -8
  373. package/ios/TopBar/ANNBarButtons.mm +397 -80
  374. package/ios/TopBar/ANNIconButtonImage.h +1 -0
  375. package/ios/TopBar/ANNIconButtonImage.mm +34 -1
  376. package/ios/TopBar/ANNLargeTitlePresenter.h +13 -0
  377. package/ios/TopBar/ANNLargeTitlePresenter.mm +50 -7
  378. package/ios/TopBar/ANNMainList.h +3 -0
  379. package/ios/TopBar/ANNMainList.mm +4 -0
  380. package/ios/TopBar/ANNScrollEdgeEffects.h +22 -6
  381. package/ios/TopBar/ANNScrollEdgeEffects.mm +123 -16
  382. package/ios/TopBar/ANNSearchPresenter.mm +172 -21
  383. package/ios/TopBar/ANNSearchResultsViewController.mm +29 -6
  384. package/ios/TopBar/ANNTopBarPresenter.h +8 -2
  385. package/ios/TopBar/ANNTopBarPresenter.mm +155 -33
  386. package/ios/TurboModules/ANNTurboEventEmitter.mm +4 -35
  387. package/ios/TurboModules/ANNTurboModule.mm +104 -33
  388. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.cpp +20 -0
  389. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.h +5 -14
  390. package/lib/module/ARCHITECTURE.md +40 -27
  391. package/lib/module/adapters/NativeANNTurboModule.js.map +1 -1
  392. package/lib/module/api/app/AppRegistry.js +14 -2
  393. package/lib/module/api/app/AppRegistry.js.map +1 -1
  394. package/lib/module/api/app/createNavigation.js +190 -66
  395. package/lib/module/api/app/createNavigation.js.map +1 -1
  396. package/lib/module/api/commands/commands.js +54 -6
  397. package/lib/module/api/commands/commands.js.map +1 -1
  398. package/lib/module/api/events/navigationEvents.js +6 -2
  399. package/lib/module/api/events/navigationEvents.js.map +1 -1
  400. package/lib/module/api/hooks/useNavigation.js +8 -3
  401. package/lib/module/api/hooks/useNavigation.js.map +1 -1
  402. package/lib/module/api/hooks/useSafeAreaInsets.js +4 -3
  403. package/lib/module/api/hooks/useSafeAreaInsets.js.map +1 -1
  404. package/lib/module/api/linking/dispatchedLinks.js +23 -0
  405. package/lib/module/api/linking/dispatchedLinks.js.map +1 -0
  406. package/lib/module/api/linking/linking.js +11 -0
  407. package/lib/module/api/linking/linking.js.map +1 -1
  408. package/lib/module/api/navigation.js.map +1 -1
  409. package/lib/module/api/options/OptionsChain.js +2 -2
  410. package/lib/module/api/screens/defineScreen.js +45 -3
  411. package/lib/module/api/screens/defineScreen.js.map +1 -1
  412. package/lib/module/api/screens/nativeScreens.js +31 -6
  413. package/lib/module/api/screens/nativeScreens.js.map +1 -1
  414. package/lib/module/api/screens/registerScreens.js +193 -35
  415. package/lib/module/api/screens/registerScreens.js.map +1 -1
  416. package/lib/module/api/theme/theme.js +5 -0
  417. package/lib/module/api/theme/theme.js.map +1 -1
  418. package/lib/module/engine/commands.js +51 -9
  419. package/lib/module/engine/commands.js.map +1 -1
  420. package/lib/module/engine/layout.js +20 -11
  421. package/lib/module/engine/layout.js.map +1 -1
  422. package/lib/module/engine/nativeScreens.js +9 -0
  423. package/lib/module/engine/nativeScreens.js.map +1 -1
  424. package/lib/module/engine/options.js +49 -15
  425. package/lib/module/engine/options.js.map +1 -1
  426. package/lib/module/engine/optionsChange.js +102 -0
  427. package/lib/module/engine/optionsChange.js.map +1 -0
  428. package/lib/module/engine/places.js +52 -7
  429. package/lib/module/engine/places.js.map +1 -1
  430. package/lib/module/engine/props.js +30 -1
  431. package/lib/module/engine/props.js.map +1 -1
  432. package/lib/module/engine/refresh.js +85 -0
  433. package/lib/module/engine/refresh.js.map +1 -0
  434. package/lib/module/engine/rememberedOptions.js +61 -1
  435. package/lib/module/engine/rememberedOptions.js.map +1 -1
  436. package/lib/module/engine/screens.js +77 -16
  437. package/lib/module/engine/screens.js.map +1 -1
  438. package/lib/module/interfaces/contract/commands.json +101 -0
  439. package/lib/module/interfaces/contract/errors.json +275 -0
  440. package/lib/typescript/adapters/NativeANNTurboModule.d.ts +12 -2
  441. package/lib/typescript/adapters/NativeANNTurboModule.d.ts.map +1 -1
  442. package/lib/typescript/api/app/AppRegistry.d.ts.map +1 -1
  443. package/lib/typescript/api/app/createNavigation.d.ts +8 -3
  444. package/lib/typescript/api/app/createNavigation.d.ts.map +1 -1
  445. package/lib/typescript/api/commands/commands.d.ts.map +1 -1
  446. package/lib/typescript/api/commands/presentation.d.ts +4 -3
  447. package/lib/typescript/api/commands/presentation.d.ts.map +1 -1
  448. package/lib/typescript/api/events/navigationEvents.d.ts +3 -3
  449. package/lib/typescript/api/events/navigationEvents.d.ts.map +1 -1
  450. package/lib/typescript/api/hooks/useNavigation.d.ts +1 -1
  451. package/lib/typescript/api/hooks/useNavigation.d.ts.map +1 -1
  452. package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts +4 -3
  453. package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts.map +1 -1
  454. package/lib/typescript/api/index.d.ts +1 -1
  455. package/lib/typescript/api/index.d.ts.map +1 -1
  456. package/lib/typescript/api/linking/dispatchedLinks.d.ts +7 -0
  457. package/lib/typescript/api/linking/dispatchedLinks.d.ts.map +1 -0
  458. package/lib/typescript/api/linking/linking.d.ts +8 -0
  459. package/lib/typescript/api/linking/linking.d.ts.map +1 -1
  460. package/lib/typescript/api/navigation.d.ts +4 -1
  461. package/lib/typescript/api/navigation.d.ts.map +1 -1
  462. package/lib/typescript/api/options/OptionsChain.d.ts +2 -2
  463. package/lib/typescript/api/screens/defineScreen.d.ts +23 -4
  464. package/lib/typescript/api/screens/defineScreen.d.ts.map +1 -1
  465. package/lib/typescript/api/screens/nativeScreens.d.ts +8 -1
  466. package/lib/typescript/api/screens/nativeScreens.d.ts.map +1 -1
  467. package/lib/typescript/api/screens/registerScreens.d.ts.map +1 -1
  468. package/lib/typescript/api/theme/theme.d.ts +2 -0
  469. package/lib/typescript/api/theme/theme.d.ts.map +1 -1
  470. package/lib/typescript/engine/commands.d.ts +5 -0
  471. package/lib/typescript/engine/commands.d.ts.map +1 -1
  472. package/lib/typescript/engine/layout.d.ts.map +1 -1
  473. package/lib/typescript/engine/nativeScreens.d.ts +5 -0
  474. package/lib/typescript/engine/nativeScreens.d.ts.map +1 -1
  475. package/lib/typescript/engine/options.d.ts +5 -2
  476. package/lib/typescript/engine/options.d.ts.map +1 -1
  477. package/lib/typescript/engine/optionsChange.d.ts +28 -0
  478. package/lib/typescript/engine/optionsChange.d.ts.map +1 -0
  479. package/lib/typescript/engine/places.d.ts +7 -2
  480. package/lib/typescript/engine/places.d.ts.map +1 -1
  481. package/lib/typescript/engine/props.d.ts +8 -1
  482. package/lib/typescript/engine/props.d.ts.map +1 -1
  483. package/lib/typescript/engine/refresh.d.ts +35 -0
  484. package/lib/typescript/engine/refresh.d.ts.map +1 -0
  485. package/lib/typescript/engine/rememberedOptions.d.ts +13 -0
  486. package/lib/typescript/engine/rememberedOptions.d.ts.map +1 -1
  487. package/lib/typescript/engine/screens.d.ts +27 -6
  488. package/lib/typescript/engine/screens.d.ts.map +1 -1
  489. package/lib/typescript/interfaces/ComponentEvents.d.ts +4 -4
  490. package/lib/typescript/interfaces/ComponentEvents.d.ts.map +1 -1
  491. package/lib/typescript/interfaces/Events.d.ts +28 -10
  492. package/lib/typescript/interfaces/Events.d.ts.map +1 -1
  493. package/lib/typescript/interfaces/Options.d.ts +1 -1
  494. package/lib/typescript/interfaces/Options.d.ts.map +1 -1
  495. package/lib/typescript/interfaces/options/animations.d.ts +80 -22
  496. package/lib/typescript/interfaces/options/animations.d.ts.map +1 -1
  497. package/lib/typescript/interfaces/options/bottomTabs.d.ts +21 -7
  498. package/lib/typescript/interfaces/options/bottomTabs.d.ts.map +1 -1
  499. package/lib/typescript/interfaces/options/buttons.d.ts +23 -15
  500. package/lib/typescript/interfaces/options/buttons.d.ts.map +1 -1
  501. package/lib/typescript/interfaces/options/modals.d.ts +34 -26
  502. package/lib/typescript/interfaces/options/modals.d.ts.map +1 -1
  503. package/lib/typescript/interfaces/options/sideMenu.d.ts +23 -6
  504. package/lib/typescript/interfaces/options/sideMenu.d.ts.map +1 -1
  505. package/lib/typescript/interfaces/options/stack.d.ts +17 -3
  506. package/lib/typescript/interfaces/options/stack.d.ts.map +1 -1
  507. package/lib/typescript/interfaces/options/system.d.ts +18 -11
  508. package/lib/typescript/interfaces/options/system.d.ts.map +1 -1
  509. package/lib/typescript/interfaces/options/toolbar.d.ts +2 -2
  510. package/lib/typescript/interfaces/options/topBar.d.ts +68 -38
  511. package/lib/typescript/interfaces/options/topBar.d.ts.map +1 -1
  512. package/metro/acceptPlugin.js +57 -0
  513. package/metro/babelTransformer.js +45 -0
  514. package/metro/index.js +36 -0
  515. package/package.json +3 -1
  516. package/src/ARCHITECTURE.md +40 -27
  517. package/src/adapters/NativeANNTurboModule.ts +12 -2
  518. package/src/api/app/AppRegistry.ts +16 -2
  519. package/src/api/app/createNavigation.ts +203 -69
  520. package/src/api/commands/commands.ts +48 -7
  521. package/src/api/commands/presentation.ts +4 -3
  522. package/src/api/events/navigationEvents.ts +10 -4
  523. package/src/api/hooks/useNavigation.ts +9 -4
  524. package/src/api/hooks/useSafeAreaInsets.ts +4 -3
  525. package/src/api/index.ts +1 -0
  526. package/src/api/linking/dispatchedLinks.ts +18 -0
  527. package/src/api/linking/linking.ts +22 -1
  528. package/src/api/navigation.ts +4 -1
  529. package/src/api/options/OptionsChain.ts +2 -2
  530. package/src/api/screens/defineScreen.ts +49 -5
  531. package/src/api/screens/nativeScreens.ts +40 -4
  532. package/src/api/screens/registerScreens.tsx +185 -42
  533. package/src/api/theme/theme.ts +5 -0
  534. package/src/engine/commands.ts +70 -13
  535. package/src/engine/layout.ts +27 -11
  536. package/src/engine/nativeScreens.ts +10 -1
  537. package/src/engine/options.ts +45 -19
  538. package/src/engine/optionsChange.ts +107 -0
  539. package/src/engine/places.ts +65 -7
  540. package/src/engine/props.ts +30 -1
  541. package/src/engine/refresh.ts +97 -0
  542. package/src/engine/rememberedOptions.ts +74 -1
  543. package/src/engine/screens.tsx +76 -21
  544. package/src/interfaces/ComponentEvents.ts +4 -4
  545. package/src/interfaces/Events.ts +29 -10
  546. package/src/interfaces/Options.ts +1 -0
  547. package/src/interfaces/contract/commands.json +101 -0
  548. package/src/interfaces/contract/errors.json +275 -0
  549. package/src/interfaces/options/animations.ts +81 -22
  550. package/src/interfaces/options/bottomTabs.ts +21 -7
  551. package/src/interfaces/options/buttons.ts +23 -15
  552. package/src/interfaces/options/modals.ts +34 -26
  553. package/src/interfaces/options/sideMenu.ts +24 -6
  554. package/src/interfaces/options/stack.ts +17 -3
  555. package/src/interfaces/options/system.ts +18 -11
  556. package/src/interfaces/options/toolbar.ts +2 -2
  557. package/src/interfaces/options/topBar.ts +68 -38
  558. package/android/src/main/java/dev/apexnative/navigation/react/ArrangementStates.kt +0 -41
  559. package/android/src/main/java/dev/apexnative/navigation/react/ScreenInsets.kt +0 -69
  560. package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationStateReporter.kt +0 -62
  561. package/android/src/main/java/dev/apexnative/navigation/react/events/StateHold.kt +0 -62
  562. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowPlacer.kt +0 -223
  563. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStub.kt +0 -31
  564. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMatrixAnimator.kt +0 -138
  565. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PlainViewAnimator.kt +0 -88
  566. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PropertyAnimatorCreator.kt +0 -33
  567. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ReactImageAnimator.kt +0 -66
  568. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextChangeAnimator.kt +0 -179
  569. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewChangeAnimator.kt +0 -139
  570. package/ios/Layouts/Screen/ANNScreenInsets.h +0 -30
  571. package/ios/Layouts/Screen/ANNScreenInsets.mm +0 -68
  572. package/ios/Layouts/Tabs/ANNTabsPreloadWindow.h +0 -27
  573. package/ios/Layouts/Tabs/ANNTabsPreloadWindow.mm +0 -55
@@ -2,126 +2,78 @@ package dev.apexnative.navigation.views.element
2
2
 
3
3
  import android.animation.Animator
4
4
  import android.animation.AnimatorListenerAdapter
5
- import android.graphics.Rect
6
5
  import android.os.Build
7
6
  import android.util.Log
8
7
  import android.view.View
9
8
  import android.view.ViewGroup
10
- import com.facebook.react.uimanager.util.ReactFindViewUtil
11
- import com.facebook.react.views.view.ReactViewGroup
12
9
  import dev.apexnative.navigation.options.ElementTransitionOptions
13
10
  import dev.apexnative.navigation.options.LayoutAnimation
14
11
  import dev.apexnative.navigation.options.SharedElementTransitionOptions
15
12
  import dev.apexnative.navigation.react.events.AppearanceDispatcher
16
13
  import dev.apexnative.navigation.utils.DevelopmentLog
17
14
  import dev.apexnative.navigation.utils.NavigationLog
15
+ import dev.apexnative.navigation.utils.SystemAnimations
18
16
  import dev.apexnative.navigation.viewcontrollers.viewcontroller.ViewController
17
+ import dev.apexnative.navigation.views.animations.AnimationLayer
19
18
  import dev.apexnative.navigation.views.animations.SideAnimator
20
19
  import dev.apexnative.navigation.views.element.animators.SharedAnimatorFactory
20
+ import java.util.Collections
21
+ import java.util.WeakHashMap
21
22
 
22
23
  /**
23
- * The elements of one transition: the element transitions and the targets of the shared elements found by their
24
- * `nativeID` (depth first, the first match) in the whole view of the screen each side shows — an element in the screen
25
- * that goes first, then in the one that comes; a pair's `fromId` in the screen that goes, its `toId` in the one that
26
- * comes. What isn't found, what is in another transition's layer and an image that isn't loaded is skipped; the rest
27
- * plays. Each view found moves into a [TransitionLayer] at its place on the screen, in the order its hierarchy draws
28
- * it, and an [ElementStub] takes its index in its parent. A pair's `from` stays where it is, hidden while its copy
29
- * flies. [finish] puts every view back at its index with its layout, its pivot and the values of its properties read
30
- * before — unless React removed its stub meanwhile: then it is gone for good —, shows the `from`s again and takes the
31
- * layer away. Main thread only.
24
+ * The elements of one transition: the element transitions and the shared pairs found by their `nativeID` (depth first,
25
+ * the first match) in the whole view of the screen each side shows — an element in the screen that goes first, then in
26
+ * the one that comes; a pair's `fromId` in the screen that goes, its `toId` in the one that comes; each screen is
27
+ * walked once for all of them ([TransitionViews]). What isn't found, what another transition plays now and an image
28
+ * that isn't loaded is skipped; so is an element whose start fails ([elementStep]): it gets its values back at once and
29
+ * the rest plays. No view leaves its parent, as on iOS. An element plays where it is, in its screen: its properties
30
+ * animate about its center and it moves with its screen. A pair flies as a copy drawn in a [TransitionLayer] over the
31
+ * screens, the copies in the order their targets are drawn; its `to` is hidden from the start, its `from` from the
32
+ * start of its flight. [finish] gives every element the values of its properties read before, shows the pairs' views
33
+ * again and takes the layer away. Main thread only.
32
34
  */
33
- internal class ElementTransition private constructor(private val layer: TransitionLayer) {
34
- // A view in the layer: where it came from and what it was.
35
- private class Moved(
36
- val view: View,
37
- val stub: ElementStub,
38
- val params: ViewGroup.LayoutParams,
39
- val frame: Rect,
40
- val values: FloatArray,
41
- val pivotSet: Boolean,
42
- // Where its parent's origin is in the layer: what `x` and `y` are counted from.
43
- val originX: Int,
44
- val originY: Int,
45
- )
35
+ internal class ElementTransition private constructor(
36
+ private val layer: TransitionLayer?,
37
+ // The views of the screens, as far as the parents that cut a pair's views count.
38
+ private val fromRoot: View?,
39
+ private val toRoot: View?,
40
+ ) {
41
+ // An element playing where it is: what it was.
42
+ private class InPlace(val view: View, val values: FloatArray, val pivotSet: Boolean)
46
43
 
47
- private val moved = ArrayList<Moved>()
48
- private val hidden = ArrayList<Pair<View, Float>>()
44
+ private val inPlace = ArrayList<InPlace>()
45
+ private val taken = ArrayList<View>()
46
+ // The views of the pairs hidden while their copies fly, with the alpha each had.
47
+ private val hidden = LinkedHashMap<View, Float>()
49
48
  private var finished = false
50
49
 
51
50
  /** The animators of the elements and of the shared elements, each with its own time. */
52
51
  val animators = ArrayList<Animator>()
53
52
 
54
- /** Every view back, the `from`s seen, the layer gone; at the end of the transition and at any stop. Once. */
53
+ /**
54
+ * Every element's values back, the pairs' views seen, the layer gone; at the end of the transition and at any stop.
55
+ * Once.
56
+ */
55
57
  fun finish() {
56
58
  if (finished) return
57
59
  finished = true
58
- for ((view, alpha) in hidden) view.alpha = alpha
60
+ for ((view, alpha) in hidden) show(view, alpha)
59
61
  hidden.clear()
60
- // Each view goes back on its own: one that can't (its parent gone wrong) doesn't keep the others in the layer.
61
- for (item in moved.asReversed()) {
62
+ // Each element on its own: one that can't get its values back doesn't keep the others from theirs.
63
+ for (item in inPlace.asReversed()) {
62
64
  try {
63
- giveBack(item)
65
+ restore(item.view, item.values, item.pivotSet)
64
66
  } catch (e: RuntimeException) {
65
- Log.w(NavigationLog.TAG, "[ApexNavigation] An element of a transition couldn't go back", e)
67
+ Log.w(NavigationLog.TAG, "[ApexNavigation] An element of a transition couldn't get its values back", e)
66
68
  }
67
69
  }
68
- moved.clear()
69
- layer.detach()
70
+ inPlace.clear()
71
+ playing -= taken.toSet()
72
+ taken.clear()
73
+ layer?.detach()
70
74
  }
71
75
 
72
- private fun moveIntoLayer(view: View): Moved? {
73
- val parent = view.parent as? ViewGroup ?: return null
74
- // A parent that clips its subviews keeps its own list of children, which a stub swapped in would leave
75
- // behind: its element stays where it is.
76
- if ((parent as? ReactViewGroup)?.removeClippedSubviews == true) return null
77
- val index = parent.indexOfChild(view)
78
- if (index < 0) return null
79
- val onScreen = IntArray(2)
80
- parent.getLocationOnScreen(onScreen)
81
- val origin = layer.originOnScreen
82
- val originX = onScreen[0] - parent.scrollX - origin.x
83
- val originY = onScreen[1] - parent.scrollY - origin.y
84
- val frame = Rect(view.left, view.top, view.right, view.bottom)
85
- val params = view.layoutParams ?: ViewGroup.LayoutParams(view.width, view.height)
86
- val pivotSet = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && view.isPivotSet
87
- val values = floatArrayOf(
88
- view.alpha, view.translationX, view.translationY, view.scaleX, view.scaleY, view.rotation,
89
- view.rotationX, view.rotationY, view.pivotX, view.pivotY,
90
- )
91
- val stub = ElementStub(view.context, view)
92
- parent.removeViewAt(index)
93
- parent.addView(stub, index, params)
94
- stub.layout(frame.left, frame.top, frame.right, frame.bottom)
95
- val left = originX + frame.left
96
- val top = originY + frame.top
97
- layer.put(view, left, top, frame.width(), frame.height())
98
- // Scale and rotations turn about the center.
99
- view.pivotX = frame.width() / 2f
100
- view.pivotY = frame.height() / 2f
101
- return Moved(view, stub, params, frame, values, pivotSet, originX, originY).also { moved += it }
102
- }
103
-
104
- private fun giveBack(item: Moved) {
105
- val view = item.view
106
- // A commit of Fabric meanwhile laid it out in its parent's coordinates: the newest such frame holds.
107
- val reactFrame = if (view.parent === layer) layer.frameFromReact(view) else null
108
- if (view.parent === layer) layer.removeView(view)
109
- restore(view, item)
110
- val parent = item.stub.parent as? ViewGroup ?: return
111
- val index = parent.indexOfChild(item.stub)
112
- if (index < 0) return
113
- parent.removeViewAt(index)
114
- parent.addView(view, index, item.params)
115
- val frame = reactFrame ?: item.frame
116
- view.measure(
117
- View.MeasureSpec.makeMeasureSpec(frame.width(), View.MeasureSpec.EXACTLY),
118
- View.MeasureSpec.makeMeasureSpec(frame.height(), View.MeasureSpec.EXACTLY),
119
- )
120
- view.layout(frame.left, frame.top, frame.right, frame.bottom)
121
- }
122
-
123
- private fun restore(view: View, item: Moved) {
124
- val values = item.values
76
+ private fun restore(view: View, values: FloatArray, pivotSet: Boolean) {
125
77
  view.alpha = values[ALPHA]
126
78
  view.translationX = values[TRANSLATION_X]
127
79
  view.translationY = values[TRANSLATION_Y]
@@ -130,7 +82,7 @@ internal class ElementTransition private constructor(private val layer: Transiti
130
82
  view.rotation = values[ROTATION]
131
83
  view.rotationX = values[ROTATION_X]
132
84
  view.rotationY = values[ROTATION_Y]
133
- if (!item.pivotSet && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
85
+ if (!pivotSet && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
134
86
  view.resetPivot()
135
87
  } else {
136
88
  view.pivotX = values[PIVOT_X]
@@ -138,34 +90,74 @@ internal class ElementTransition private constructor(private val layer: Transiti
138
90
  }
139
91
  }
140
92
 
141
- private fun addElement(options: ElementTransitionOptions, item: Moved) {
142
- val base = SideAnimator.Base(xOffset = item.originX.toFloat(), yOffset = item.originY.toFloat())
143
- SideAnimator.build(item.view, options, base)?.let(animators::add)
93
+ // An element with views in it fades through a hardware layer only where its alpha would draw it into an offscreen
94
+ // buffer at every frame (AnimationLayer: its rendering overlaps). React's views overlap only with
95
+ // `needsOffscreenAlphaCompositing`, so most elements fade without one and nothing they draw outside their bounds (a
96
+ // box shadow) is clipped. A view without children fades its own drawing at no extra cost. Scale and rotations turn
97
+ // about the element's center; `x` and `y` are its place in its own parent.
98
+ private fun addElement(options: ElementTransitionOptions, view: View) {
99
+ inPlace += InPlace(view, valuesOf(view), pivotSetOf(view))
100
+ view.pivotX = view.width / 2f
101
+ view.pivotY = view.height / 2f
102
+ val animator = SideAnimator.build(view, options, SideAnimator.Base()) ?: return
103
+ if (view is ViewGroup) AnimationLayer.during(view, animator)
104
+ animators += animator
144
105
  }
145
106
 
146
- // The pair's flight: `to` hidden until it starts, `from` hidden from its start; false when it doesn't fly.
107
+ // An element whose start failed gets its values back now.
108
+ private fun giveValuesBack(view: View) {
109
+ val item = inPlace.lastOrNull { it.view === view } ?: return
110
+ inPlace -= item
111
+ try {
112
+ restore(view, item.values, item.pivotSet)
113
+ } catch (e: RuntimeException) {
114
+ Log.w(NavigationLog.TAG, "[ApexNavigation] An element of a transition couldn't get its values back", e)
115
+ }
116
+ }
117
+
118
+ // The pair's flight: `to` hidden from now, `from` from its start, both seen again when it stops or its copy can't
119
+ // be drawn. Nothing changes when it doesn't fly.
147
120
  private fun addPair(
148
121
  options: SharedElementTransitionOptions,
149
122
  from: View,
150
- item: Moved,
151
- toParent: View?,
123
+ to: View,
124
+ name: String,
152
125
  fallbackDuration: Long,
153
- ): Boolean {
154
- val to = item.view
126
+ ) {
127
+ val layer = layer ?: return
155
128
  val flight = SharedAnimatorFactory.create(
156
- from, to, toParent, layer, options, fallbackDuration, DevelopmentLog::warn,
157
- ) ?: return false
158
- val alpha = item.values[ALPHA]
159
- to.alpha = 0f
160
- hidden += from to from.alpha
129
+ from, to, fromRoot, toRoot, layer, options, fallbackDuration, DevelopmentLog::warn,
130
+ ) ?: return
131
+ val fromAlpha = from.alpha
132
+ val seenAgain = {
133
+ flight.picture.shown = false
134
+ hidden.remove(from)?.let { show(from, it) }
135
+ hidden.remove(to)?.let { show(to, it) }
136
+ layer.invalidate()
137
+ }
138
+ flight.picture.onFailed = { e ->
139
+ elementSkipped(name, e.toString())
140
+ seenAgain()
141
+ }
161
142
  flight.animator.addListener(object : AnimatorListenerAdapter() {
143
+ private var stopped = false
144
+
162
145
  override fun onAnimationStart(animation: Animator) {
146
+ if (stopped || finished) return
147
+ hidden[from] = fromAlpha
163
148
  from.alpha = 0f
164
- if (!flight.drawsPictures) to.alpha = alpha
149
+ }
150
+
151
+ // A flight whose start or frame failed stops (`MoveAnimator`), maybe inside its own start.
152
+ override fun onAnimationCancel(animation: Animator) {
153
+ stopped = true
154
+ seenAgain()
165
155
  }
166
156
  })
157
+ layer.add(flight.picture)
158
+ hidden[to] = to.alpha
159
+ to.alpha = 0f
167
160
  animators += flight.animator
168
- return true
169
161
  }
170
162
 
171
163
  companion object {
@@ -180,10 +172,26 @@ internal class ElementTransition private constructor(private val layer: Transiti
180
172
  private const val PIVOT_X = 8
181
173
  private const val PIVOT_Y = 9
182
174
 
175
+ // The views the transitions that run now play: another transition leaves them alone.
176
+ private val playing: MutableSet<View> = Collections.newSetFromMap(WeakHashMap())
177
+
178
+ private fun valuesOf(view: View) = floatArrayOf(
179
+ view.alpha, view.translationX, view.translationY, view.scaleX, view.scaleY, view.rotation,
180
+ view.rotationX, view.rotationY, view.pivotX, view.pivotY,
181
+ )
182
+
183
+ private fun pivotSetOf(view: View) = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && view.isPivotSet
184
+
185
+ // A view hidden for a flight shows again with its alpha, unless React gave it another one meanwhile. React
186
+ // writes the same alpha: an opacity it commits during the flight shows the view beside its copy until the end.
187
+ private fun show(view: View, alpha: Float) {
188
+ if (view.alpha == 0f) view.alpha = alpha
189
+ }
190
+
183
191
  /**
184
- * The elements of [animation] from [from] to [to], moved into a layer that joins [host] at [layerIndex] (its
185
- * top without one); none when none of them is found. A shared element without a duration takes
186
- * [fallbackDuration], the screen's fade.
192
+ * The elements of [animation] from [from] to [to]; the copies of the pairs in a layer that joins [host] at
193
+ * [layerIndex] (its top without one). None when none of them is found or the system's animations are off. A
194
+ * shared element without a duration takes [fallbackDuration], the screen's fade.
187
195
  */
188
196
  fun start(
189
197
  animation: LayoutAnimation,
@@ -193,33 +201,38 @@ internal class ElementTransition private constructor(private val layer: Transiti
193
201
  layerIndex: Int?,
194
202
  fallbackDuration: Long,
195
203
  ): ElementTransition? {
204
+ if (SystemAnimations.areOff(host.context)) return null
196
205
  val fromView = from?.let { AppearanceDispatcher.visibleNode(it).peekView() }
197
206
  val toView = AppearanceDispatcher.visibleNode(to).peekView()
207
+ val transitions = animation.elementTransitions.transitions
208
+ val shared = animation.sharedElements.get()
209
+ val views = TransitionViews(shared, transitions, fromView, toView)
198
210
  val taken = HashSet<View>()
199
211
  val elements = ArrayList<Pair<ElementTransitionOptions, View>>()
200
- for (element in animation.elementTransitions.transitions) {
212
+ for (element in transitions) {
201
213
  if (element.id.isEmpty()) continue
202
- val view = find(fromView, element.id) ?: find(toView, element.id) ?: continue
203
- if (TransitionLayer.holds(view) || !taken.add(view)) continue
214
+ val view = views.leaving(element.id) ?: views.arriving(element.id) ?: continue
215
+ if (view in playing || !taken.add(view)) continue
204
216
  elements += element to view
205
217
  }
206
218
  val pairs = ArrayList<Triple<SharedElementTransitionOptions, View, View>>()
207
- for (pair in animation.sharedElements.get()) {
219
+ for (pair in shared) {
208
220
  val fromId = pair.fromId.get(null) ?: continue
209
221
  val toId = pair.toId.get(null) ?: continue
210
- val source = find(fromView, fromId) ?: continue
211
- val target = find(toView, toId) ?: continue
212
- if (source === target || TransitionLayer.holds(source) || TransitionLayer.holds(target)) continue
222
+ val source = views.leaving(fromId) ?: continue
223
+ val target = views.arriving(toId) ?: continue
224
+ if (source === target || source in playing || target in playing) continue
213
225
  if (target in taken || source in taken) continue
214
226
  if (!loaded(source, fromId) || !loaded(target, toId)) continue
227
+ taken += source
215
228
  taken += target
216
229
  pairs += Triple(pair, source, target)
217
230
  }
218
231
  if (elements.isEmpty() && pairs.isEmpty()) return null
219
- val layer = TransitionLayer(host.context)
220
- val transition = ElementTransition(layer)
232
+ val layer = if (pairs.isEmpty()) null else TransitionLayer(host.context)
233
+ val transition = ElementTransition(layer, fromView, toView)
221
234
  try {
222
- layer.attachTo(host, layerIndex ?: host.childCount)
235
+ layer?.attachTo(host, layerIndex ?: host.childCount)
223
236
  transition.fill(host, elements, pairs, fallbackDuration)
224
237
  } catch (e: RuntimeException) {
225
238
  transition.finish()
@@ -229,8 +242,8 @@ internal class ElementTransition private constructor(private val layer: Transiti
229
242
  }
230
243
 
231
244
  /**
232
- * [start], and when that fails, a line in the log and none: the screens play without their elements; every view
233
- * moved is back already.
245
+ * [start], and when that fails, a line in the log and none: the screens play without their elements; every
246
+ * element has its values back already.
234
247
  */
235
248
  fun startOrLog(
236
249
  animation: LayoutAnimation,
@@ -246,9 +259,6 @@ internal class ElementTransition private constructor(private val layer: Transiti
246
259
  null
247
260
  }
248
261
 
249
- private fun find(root: View?, nativeId: String): View? =
250
- root?.let { ReactFindViewUtil.findView(it, nativeId) }?.takeUnless { it is ElementStub }
251
-
252
262
  // An image not loaded drops out of the transition; its wait logged it already, else it is logged now.
253
263
  private fun loaded(view: View, id: String): Boolean {
254
264
  if (ImageLoads.isLoaded(view)) return true
@@ -257,25 +267,23 @@ internal class ElementTransition private constructor(private val layer: Transiti
257
267
  }
258
268
  }
259
269
 
260
- // The views into the layer in the order they are drawn, then their animators; a pair that doesn't fly goes back at
261
- // once.
270
+ // The elements' animators where they are, then the pairs' flights, their copies in the order their targets are
271
+ // drawn. Each element's steps run on their own ([elementStep]): one that fails is left as it was, the others play.
262
272
  private fun fill(
263
273
  host: ViewGroup,
264
274
  elements: List<Pair<ElementTransitionOptions, View>>,
265
275
  pairs: List<Triple<SharedElementTransitionOptions, View, View>>,
266
276
  fallbackDuration: Long,
267
277
  ) {
268
- val views = elements.map { it.second } + pairs.map { it.third }
269
- val parents = views.associateWith { it.parent as? View }
270
- val placed = HashMap<View, Moved>()
271
- for (view in DrawOrder.sorted(views, host) { it }) moveIntoLayer(view)?.let { placed[view] = it }
272
- for ((options, view) in elements) placed[view]?.let { addElement(options, it) }
273
- for ((options, source, target) in pairs) {
274
- val item = placed[target] ?: continue
275
- if (!addPair(options, source, item, parents[target], fallbackDuration)) {
276
- moved -= item
277
- giveBack(item)
278
- }
278
+ for ((_, view) in elements) taken += view
279
+ for ((_, source, target) in pairs) taken += listOf(source, target)
280
+ playing += taken
281
+ for ((options, view) in elements) {
282
+ if (!elementStep(elementName(options.id)) { addElement(options, view) }) giveValuesBack(view)
283
+ }
284
+ for ((options, source, target) in DrawOrder.sorted(pairs, host) { it.third }) {
285
+ val name = pairName(options.fromId.get(""), options.toId.get(""))
286
+ elementStep(name) { addPair(options, source, target, name, fallbackDuration) }
279
287
  }
280
288
  }
281
289
  }
@@ -3,11 +3,11 @@ package dev.apexnative.navigation.views.element
3
3
  import android.util.Log
4
4
  import android.view.Choreographer
5
5
  import android.view.View
6
- import com.facebook.react.uimanager.util.ReactFindViewUtil
7
6
  import dev.apexnative.navigation.options.LayoutAnimation
8
7
  import dev.apexnative.navigation.react.events.AppearanceDispatcher
9
8
  import dev.apexnative.navigation.utils.DevelopmentLog
10
9
  import dev.apexnative.navigation.utils.NavigationLog
10
+ import dev.apexnative.navigation.utils.SystemAnimations
11
11
  import dev.apexnative.navigation.viewcontrollers.viewcontroller.ViewController
12
12
  import kotlinx.coroutines.CancellationException
13
13
  import kotlinx.coroutines.CoroutineScope
@@ -18,7 +18,8 @@ import kotlinx.coroutines.launch
18
18
  /**
19
19
  * The wait of a forward transition with elements for its targets: the module's frames (`awaitTransitionTargets`, 0.5 s
20
20
  * at most, then one frame more), then the images of the shared elements found ([ImageWait], 1 s at most each). It ends
21
- * early when the screen that goes is destroyed. A failure in it is logged and the transition starts. Main thread only.
21
+ * early when the screen that goes is destroyed, and doesn't wait with the system's animations off. A failure in it is
22
+ * logged and the transition starts. Main thread only.
22
23
  */
23
24
  internal object TargetsWait {
24
25
  // The waits run on the main thread's frames; each is cancelled on its own.
@@ -32,6 +33,11 @@ internal object TargetsWait {
32
33
  waiting: () -> Boolean,
33
34
  done: () -> Unit,
34
35
  ): () -> Unit {
36
+ // With the system's animations off no element moves ([ElementTransition.start]): nothing to wait for.
37
+ if (SystemAnimations.areOff(to.peekView()?.context)) {
38
+ guarded { done() }
39
+ return NOTHING
40
+ }
35
41
  var stopped = false
36
42
  var stopImages: () -> Unit = NOTHING
37
43
  val still = { !stopped && waiting() && from?.isDestroyed != true }
@@ -72,12 +78,14 @@ internal object TargetsWait {
72
78
  ): () -> Unit {
73
79
  val fromView = from?.let { AppearanceDispatcher.visibleNode(it).peekView() }
74
80
  val toView = AppearanceDispatcher.visibleNode(to).peekView()
81
+ val pairs = animation.sharedElements.get()
82
+ val views = TransitionViews(pairs, emptyList(), fromView, toView)
75
83
  val images = ArrayList<ImageWait.Image?>()
76
- for (pair in animation.sharedElements.get()) {
84
+ for (pair in pairs) {
77
85
  val fromId = pair.fromId.get(null) ?: continue
78
86
  val toId = pair.toId.get(null) ?: continue
79
- val source = fromView?.let { ReactFindViewUtil.findView(it, fromId) } ?: continue
80
- val target = toView?.let { ReactFindViewUtil.findView(it, toId) } ?: continue
87
+ val source = views.leaving(fromId) ?: continue
88
+ val target = views.arriving(toId) ?: continue
81
89
  images += imageOf(source, fromId)
82
90
  images += imageOf(target, toId)
83
91
  }
@@ -2,45 +2,35 @@ package dev.apexnative.navigation.views.element
2
2
 
3
3
  import android.annotation.SuppressLint
4
4
  import android.content.Context
5
- import android.graphics.Point
6
- import android.graphics.Rect
5
+ import android.graphics.Canvas
7
6
  import android.view.MotionEvent
8
7
  import android.view.View
9
8
  import android.view.ViewGroup
9
+ import dev.apexnative.navigation.views.element.animators.FlightPicture
10
10
 
11
11
  /**
12
- * The layer of a transition's elements: full size over the screens' common parent (a stack's view; for a modal, between
13
- * the modals layer and the overlays layer), there only while the transition runs. Each view in it lies where its layout
14
- * params say — `leftMargin`, `topMargin` and its size, in the layer's pixels — and nothing re-places it: Fabric's views
15
- * carry no margins of their own. Nothing in it is clipped by the parents it came from, it takes no touches,
16
- * accessibility doesn't see it. Main thread only.
12
+ * The layer the copies of a transition's shared elements fly in: full size over the screens' common parent (a stack's
13
+ * view; for a modal, between the modals layer and the overlays layer), there only while the transition runs. It holds
14
+ * no views: it draws the pictures of the flights ([FlightPicture]) in the order they are added, each while it is shown,
15
+ * on every frame while one of them is [FlightPicture.live]. A picture whose drawing fails draws no more, and its
16
+ * [FlightPicture.onFailed] runs after the frame. It takes no touches, accessibility doesn't see it. Main thread only.
17
17
  */
18
18
  @SuppressLint("ViewConstructor")
19
- internal class TransitionLayer(context: Context) : ViewGroup(context) {
20
- // The newest frame Fabric gave a view while it was here (a commit lays it out in its parent's coordinates).
21
- private val reactFrames = HashMap<View, Rect>()
19
+ internal class TransitionLayer(context: Context) : View(context) {
20
+ private val pictures = ArrayList<FlightPicture>()
22
21
 
23
22
  init {
24
- clipChildren = false
25
- clipToPadding = false
26
- importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
23
+ importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_NO
24
+ setWillNotDraw(false)
27
25
  }
28
26
 
29
- /** The layer's top left corner on the screen, in pixels: what the views in it are placed from. */
30
- val originOnScreen: Point
31
- get() {
32
- val location = IntArray(2)
33
- getLocationOnScreen(location)
34
- return Point(location[0], location[1])
35
- }
36
-
37
27
  /**
38
- * Joins [parent] at [index] (its top without one), laid out at once at the parent's size: its views are in their
39
- * places on the frame the transition starts.
28
+ * Joins [parent] at [index] (its top without one), laid out at once at the parent's size: the places of the views
29
+ * are measured from it on the frame the transition starts.
40
30
  */
41
31
  fun attachTo(parent: ViewGroup, index: Int = parent.childCount) {
42
32
  // The parent turns these into its own kind of params.
43
- parent.addView(this, index.coerceIn(0, parent.childCount), LayoutParams(MATCH, MATCH))
33
+ parent.addView(this, index.coerceIn(0, parent.childCount), ViewGroup.LayoutParams(MATCH, MATCH))
44
34
  measure(
45
35
  MeasureSpec.makeMeasureSpec(parent.width, MeasureSpec.EXACTLY),
46
36
  MeasureSpec.makeMeasureSpec(parent.height, MeasureSpec.EXACTLY),
@@ -48,51 +38,10 @@ internal class TransitionLayer(context: Context) : ViewGroup(context) {
48
38
  layout(0, 0, parent.width, parent.height)
49
39
  }
50
40
 
51
- /** [view] lies at [left], [top] (the layer's pixels) at the size [width] × [height], laid out at once. */
52
- fun put(view: View, left: Int, top: Int, width: Int, height: Int) {
53
- val params = MarginLayoutParams(width, height).apply {
54
- leftMargin = left
55
- topMargin = top
56
- }
57
- addView(view, params)
58
- layOut(view, left, top, width, height)
59
- }
60
-
61
- /** [view], in the layer, lies at [left], [top] at the size [width] × [height] from now on. */
62
- fun place(view: View, left: Int, top: Int, width: Int, height: Int) {
63
- noteReactFrame(view)
64
- (view.layoutParams as? MarginLayoutParams)?.let {
65
- it.leftMargin = left
66
- it.topMargin = top
67
- it.width = width
68
- it.height = height
69
- }
70
- layOut(view, left, top, width, height)
71
- }
72
-
73
- private fun layOut(view: View, left: Int, top: Int, width: Int, height: Int) {
74
- view.measure(
75
- MeasureSpec.makeMeasureSpec(width.coerceAtLeast(0), MeasureSpec.EXACTLY),
76
- MeasureSpec.makeMeasureSpec(height.coerceAtLeast(0), MeasureSpec.EXACTLY),
77
- )
78
- view.layout(left, top, left + width, top + height)
79
- }
80
-
81
- /**
82
- * The newest frame React gave [view] while it was in the layer, in its parent's coordinates; none when React
83
- * didn't lay it out meanwhile. A frame other than the one the layer gave it can only be React's.
84
- */
85
- fun frameFromReact(view: View): Rect? {
86
- noteReactFrame(view)
87
- return reactFrames.remove(view)
88
- }
89
-
90
- // The view's frame isn't where the layer put it: React laid it out since.
91
- private fun noteReactFrame(view: View) {
92
- val params = view.layoutParams as? MarginLayoutParams ?: return
93
- val placed = view.left == params.leftMargin && view.top == params.topMargin &&
94
- view.width == params.width && view.height == params.height
95
- if (!placed) reactFrames[view] = Rect(view.left, view.top, view.right, view.bottom)
41
+ /** [picture] is drawn over those added before it. */
42
+ fun add(picture: FlightPicture) {
43
+ pictures += picture
44
+ invalidate()
96
45
  }
97
46
 
98
47
  /** The layer leaves its parent. */
@@ -100,53 +49,29 @@ internal class TransitionLayer(context: Context) : ViewGroup(context) {
100
49
  (parent as? ViewGroup)?.removeView(this)
101
50
  }
102
51
 
103
- override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
104
- setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec))
105
- for (index in 0 until childCount) {
106
- val child = getChildAt(index)
107
- val params = child.layoutParams
108
- child.measure(
109
- MeasureSpec.makeMeasureSpec(params.width.coerceAtLeast(0), MeasureSpec.EXACTLY),
110
- MeasureSpec.makeMeasureSpec(params.height.coerceAtLeast(0), MeasureSpec.EXACTLY),
111
- )
112
- }
113
- }
114
-
115
- override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
116
- for (index in 0 until childCount) {
117
- val child = getChildAt(index)
118
- val params = child.layoutParams as? MarginLayoutParams ?: continue
119
- noteReactFrame(child)
120
- child.layout(
121
- params.leftMargin,
122
- params.topMargin,
123
- params.leftMargin + child.measuredWidth,
124
- params.topMargin + child.measuredHeight,
125
- )
52
+ override fun onDraw(canvas: Canvas) {
53
+ var live = false
54
+ for (picture in pictures) {
55
+ if (!picture.shown) continue
56
+ live = live || picture.live
57
+ val count = canvas.save()
58
+ try {
59
+ picture.draw(canvas)
60
+ } catch (e: RuntimeException) {
61
+ picture.shown = false
62
+ post { picture.onFailed(e) }
63
+ } finally {
64
+ canvas.restoreToCount(count)
65
+ }
126
66
  }
67
+ // A landed copy gets no more frames from its flight: one that changes by itself asks for them.
68
+ if (live) postInvalidateOnAnimation()
127
69
  }
128
70
 
129
- override fun checkLayoutParams(params: LayoutParams?): Boolean = params is MarginLayoutParams
130
-
131
- override fun generateDefaultLayoutParams(): LayoutParams = MarginLayoutParams(0, 0)
132
-
133
- override fun generateLayoutParams(params: LayoutParams?): LayoutParams = MarginLayoutParams(params)
134
-
71
+ @SuppressLint("ClickableViewAccessibility")
135
72
  override fun dispatchTouchEvent(event: MotionEvent?): Boolean = false
136
73
 
137
- override fun shouldDelayChildPressedState(): Boolean = false
138
-
139
- companion object {
140
- private const val MATCH = LayoutParams.MATCH_PARENT
141
-
142
- /** Whether [view] is in a transition's layer now (an element of another transition). */
143
- fun holds(view: View): Boolean {
144
- var parent = view.parent
145
- while (parent != null) {
146
- if (parent is TransitionLayer) return true
147
- parent = parent.parent
148
- }
149
- return false
150
- }
74
+ private companion object {
75
+ const val MATCH = ViewGroup.LayoutParams.MATCH_PARENT
151
76
  }
152
77
  }