@apexnative/navigation 1.0.0-alpha.6 → 1.0.0-alpha.8

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 (242) hide show
  1. package/ApexNavigation.podspec +2 -1
  2. package/CHANGELOG.md +15 -0
  3. package/android/CLAUDE.md +19 -10
  4. package/android/CORE.md +3 -2
  5. package/android/consumer-rules.pro +6 -0
  6. package/android/src/main/java/dev/apexnative/navigation/options/BottomTabOptions.kt +1 -1
  7. package/android/src/main/java/dev/apexnative/navigation/options/ButtonOptions.kt +1 -1
  8. package/android/src/main/java/dev/apexnative/navigation/options/LargeTitleOptions.kt +1 -1
  9. package/android/src/main/java/dev/apexnative/navigation/options/LayoutAnimation.kt +1 -1
  10. package/android/src/main/java/dev/apexnative/navigation/options/OptionKey.kt +18 -0
  11. package/android/src/main/java/dev/apexnative/navigation/options/OptionPaths.kt +91 -0
  12. package/android/src/main/java/dev/apexnative/navigation/options/SheetOptions.kt +7 -4
  13. package/android/src/main/java/dev/apexnative/navigation/options/TitleOptions.kt +2 -2
  14. package/android/src/main/java/dev/apexnative/navigation/options/TopBarAppearanceOptions.kt +1 -1
  15. package/android/src/main/java/dev/apexnative/navigation/options/TopBarOptions.kt +16 -7
  16. package/android/src/main/java/dev/apexnative/navigation/react/ContentHeights.kt +95 -0
  17. package/android/src/main/java/dev/apexnative/navigation/react/ContentMounts.kt +66 -0
  18. package/android/src/main/java/dev/apexnative/navigation/react/NavigationTurboModule.kt +4 -0
  19. package/android/src/main/java/dev/apexnative/navigation/react/OptionsCommands.kt +41 -3
  20. package/android/src/main/java/dev/apexnative/navigation/react/ReactView.kt +16 -1
  21. package/android/src/main/java/dev/apexnative/navigation/slots/SlotScreenView.kt +27 -7
  22. package/android/src/main/java/dev/apexnative/navigation/slots/SlotView.kt +12 -1
  23. package/android/src/main/java/dev/apexnative/navigation/utils/MaterialTheme.kt +5 -6
  24. package/android/src/main/java/dev/apexnative/navigation/utils/SystemAnimations.kt +36 -0
  25. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalSheet.kt +329 -55
  26. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalViews.kt +26 -5
  27. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetStops.kt +60 -2
  28. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuMotion.kt +8 -2
  29. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/BackPreview.kt +32 -4
  30. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackController.kt +46 -7
  31. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackQueue.kt +15 -3
  32. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackViews.kt +7 -4
  33. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabMotion.kt +142 -0
  34. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabPresenter.kt +215 -43
  35. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/StackSearchPresenter.kt +25 -26
  36. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarRowTransition.kt +3 -2
  37. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/ButtonPlaces.kt +11 -5
  38. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarPresenter.kt +86 -39
  39. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarVisibility.kt +9 -2
  40. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementTransitions.kt +124 -181
  41. package/android/src/main/java/dev/apexnative/navigation/views/element/TargetsWait.kt +8 -1
  42. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionLayer.kt +37 -112
  43. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ElementPictures.kt +56 -3
  44. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/FlightGeometry.kt +170 -153
  45. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMorph.kt +199 -0
  46. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/SharedAnimatorFactory.kt +55 -45
  47. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/{TextChangeAnimator.kt → TextMorph.kt} +79 -129
  48. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewMorph.kt +108 -0
  49. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabCopy.kt +85 -0
  50. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabMenu.kt +13 -0
  51. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TitleBar.kt +5 -24
  52. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TopBar.kt +51 -34
  53. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonComponentCell.kt +6 -6
  54. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonView.kt +113 -0
  55. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarMenu.kt +219 -0
  56. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonBar.kt +121 -175
  57. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonMenus.kt +34 -64
  58. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonRow.kt +216 -0
  59. package/android/src/main/jni/ANNContentHeights.cpp +82 -0
  60. package/android/src/main/res/drawable/apex_navigation_ic_arrow_right.xml +14 -0
  61. package/android/src/main/res/layout/apex_navigation_menu_header.xml +19 -0
  62. package/android/src/main/res/layout/apex_navigation_menu_item.xml +68 -0
  63. package/android/src/main/res/values/styles.xml +1 -1
  64. package/android/src/main/res/values-night/styles.xml +1 -1
  65. package/cli/doctor/checks/app.js +16 -1
  66. package/cli/project.js +4 -0
  67. package/cli/setup/index.js +5 -0
  68. package/cli/setup/steps/metro.js +46 -0
  69. package/docs-md/architecture/native-screens.md +4 -0
  70. package/docs-md/architecture/theme-and-context.md +131 -12
  71. package/docs-md/architecture/transitions.md +43 -4
  72. package/docs-md/flows/bottom-sheets.md +4 -2
  73. package/docs-md/fundamentals/screens-and-props.md +9 -1
  74. package/docs-md/guides/cli.md +3 -1
  75. package/docs-md/help/troubleshooting.md +1 -1
  76. package/docs-md/index.json +29 -1
  77. package/docs-md/screen-ui/back-and-gestures.md +3 -1
  78. package/docs-md/screen-ui/bar-buttons.md +1 -1
  79. package/docs-md/screen-ui/toolbar-and-fab.md +2 -0
  80. package/docs-md/start/installation.md +16 -1
  81. package/ios/Animations/ANNFrameDriver.h +55 -15
  82. package/ios/Animations/ANNFrameDriver.mm +214 -60
  83. package/ios/Animations/ANNTransitionAnimator.h +26 -5
  84. package/ios/Animations/ANNTransitionAnimator.mm +49 -3
  85. package/ios/Animations/ANNTransitionPlan.h +2 -2
  86. package/ios/Animations/ANNTransitionPlan.mm +10 -0
  87. package/ios/Animations/Elements/ANNElementFinder.h +2 -2
  88. package/ios/Animations/Elements/ANNElementFinder.mm +2 -2
  89. package/ios/Animations/Elements/ANNElementTransition.h +3 -3
  90. package/ios/Animations/Elements/ANNElementTransition.mm +2 -2
  91. package/ios/Animations/Elements/ANNSharedElementFlight.h +3 -3
  92. package/ios/Animations/Elements/ANNSharedElementFlight.mm +181 -43
  93. package/ios/Animations/Interpolators/ANNViewTracks.h +6 -5
  94. package/ios/Animations/Interpolators/ANNViewTracks.mm +51 -21
  95. package/ios/CLAUDE.md +19 -8
  96. package/ios/CORE.md +1 -1
  97. package/ios/Core/ANNAppDelegate.mm +0 -2
  98. package/ios/Core/ANNDeepLinkQueue.h +6 -5
  99. package/ios/Core/ANNDeepLinkQueue.mm +22 -10
  100. package/ios/Core/ANNSceneDelegate.mm +2 -2
  101. package/ios/Core/ANNUtils.h +7 -0
  102. package/ios/Core/ANNUtils.mm +10 -0
  103. package/ios/Core/ApexNavigation.mm +6 -2
  104. package/ios/Layouts/Overlay/ANNOverlayCoordinator.mm +1 -7
  105. package/ios/Layouts/Root/ANNRootCoordinator.mm +45 -15
  106. package/ios/Layouts/Screen/ANNComponentViewController.mm +4 -1
  107. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.h +11 -2
  108. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.mm +14 -7
  109. package/ios/Layouts/Stack/ANNStackController.h +8 -0
  110. package/ios/Layouts/Stack/ANNStackController.mm +153 -11
  111. package/ios/Layouts/Stack/ANNSwipePopInteraction.h +26 -0
  112. package/ios/Layouts/Stack/ANNSwipePopInteraction.mm +185 -0
  113. package/ios/Layouts/Stack/InteractivePopGestureDelegate.mm +28 -4
  114. package/ios/Layouts/Tabs/ANNTabsPreloadWindow.mm +2 -4
  115. package/ios/Options/ANNAnimationOptions.h +2 -1
  116. package/ios/Options/ANNAnimationOptions.mm +1 -1
  117. package/ios/Options/ANNOptions.h +7 -0
  118. package/ios/Options/ANNOptions.mm +45 -0
  119. package/ios/Options/ANNOptionsReader.mm +2 -4
  120. package/ios/Options/ANNStackPopAnimationOptions.h +13 -0
  121. package/ios/Options/ANNStackPopAnimationOptions.mm +11 -0
  122. package/ios/Options/Params/ColorParser.h +4 -3
  123. package/ios/Options/Params/ColorParser.mm +22 -4
  124. package/ios/React/ANNSurfaceHostingView.h +8 -0
  125. package/ios/React/ANNSurfaceHostingView.mm +28 -1
  126. package/ios/React/Slots/ANNSlotHost.mm +1 -3
  127. package/ios/React/Slots/ANNSlotScreenView.mm +8 -2
  128. package/ios/TurboModules/ANNTurboModule.mm +46 -0
  129. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.cpp +20 -0
  130. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.h +5 -14
  131. package/lib/module/ARCHITECTURE.md +9 -3
  132. package/lib/module/adapters/NativeANNTurboModule.js.map +1 -1
  133. package/lib/module/api/app/AppRegistry.js +14 -2
  134. package/lib/module/api/app/AppRegistry.js.map +1 -1
  135. package/lib/module/api/app/createNavigation.js +188 -66
  136. package/lib/module/api/app/createNavigation.js.map +1 -1
  137. package/lib/module/api/events/navigationEvents.js +6 -2
  138. package/lib/module/api/events/navigationEvents.js.map +1 -1
  139. package/lib/module/api/linking/linking.js +11 -0
  140. package/lib/module/api/linking/linking.js.map +1 -1
  141. package/lib/module/api/screens/defineScreen.js +45 -3
  142. package/lib/module/api/screens/defineScreen.js.map +1 -1
  143. package/lib/module/api/screens/nativeScreens.js +31 -6
  144. package/lib/module/api/screens/nativeScreens.js.map +1 -1
  145. package/lib/module/api/screens/registerScreens.js +193 -35
  146. package/lib/module/api/screens/registerScreens.js.map +1 -1
  147. package/lib/module/api/theme/theme.js +5 -0
  148. package/lib/module/api/theme/theme.js.map +1 -1
  149. package/lib/module/engine/commands.js +21 -1
  150. package/lib/module/engine/commands.js.map +1 -1
  151. package/lib/module/engine/layout.js +7 -2
  152. package/lib/module/engine/layout.js.map +1 -1
  153. package/lib/module/engine/nativeScreens.js +9 -0
  154. package/lib/module/engine/nativeScreens.js.map +1 -1
  155. package/lib/module/engine/options.js +5 -4
  156. package/lib/module/engine/options.js.map +1 -1
  157. package/lib/module/engine/optionsChange.js +102 -0
  158. package/lib/module/engine/optionsChange.js.map +1 -0
  159. package/lib/module/engine/refresh.js +85 -0
  160. package/lib/module/engine/refresh.js.map +1 -0
  161. package/lib/module/engine/rememberedOptions.js +60 -0
  162. package/lib/module/engine/rememberedOptions.js.map +1 -1
  163. package/lib/module/engine/screens.js +26 -0
  164. package/lib/module/engine/screens.js.map +1 -1
  165. package/lib/typescript/adapters/NativeANNTurboModule.d.ts +7 -0
  166. package/lib/typescript/adapters/NativeANNTurboModule.d.ts.map +1 -1
  167. package/lib/typescript/api/app/AppRegistry.d.ts.map +1 -1
  168. package/lib/typescript/api/app/createNavigation.d.ts +5 -0
  169. package/lib/typescript/api/app/createNavigation.d.ts.map +1 -1
  170. package/lib/typescript/api/events/navigationEvents.d.ts +2 -2
  171. package/lib/typescript/api/events/navigationEvents.d.ts.map +1 -1
  172. package/lib/typescript/api/index.d.ts +1 -1
  173. package/lib/typescript/api/index.d.ts.map +1 -1
  174. package/lib/typescript/api/linking/linking.d.ts +8 -0
  175. package/lib/typescript/api/linking/linking.d.ts.map +1 -1
  176. package/lib/typescript/api/screens/defineScreen.d.ts +23 -4
  177. package/lib/typescript/api/screens/defineScreen.d.ts.map +1 -1
  178. package/lib/typescript/api/screens/nativeScreens.d.ts +8 -1
  179. package/lib/typescript/api/screens/nativeScreens.d.ts.map +1 -1
  180. package/lib/typescript/api/screens/registerScreens.d.ts.map +1 -1
  181. package/lib/typescript/api/theme/theme.d.ts +2 -0
  182. package/lib/typescript/api/theme/theme.d.ts.map +1 -1
  183. package/lib/typescript/engine/commands.d.ts +5 -0
  184. package/lib/typescript/engine/commands.d.ts.map +1 -1
  185. package/lib/typescript/engine/layout.d.ts.map +1 -1
  186. package/lib/typescript/engine/nativeScreens.d.ts +5 -0
  187. package/lib/typescript/engine/nativeScreens.d.ts.map +1 -1
  188. package/lib/typescript/engine/optionsChange.d.ts +28 -0
  189. package/lib/typescript/engine/optionsChange.d.ts.map +1 -0
  190. package/lib/typescript/engine/refresh.d.ts +35 -0
  191. package/lib/typescript/engine/refresh.d.ts.map +1 -0
  192. package/lib/typescript/engine/rememberedOptions.d.ts +13 -0
  193. package/lib/typescript/engine/rememberedOptions.d.ts.map +1 -1
  194. package/lib/typescript/engine/screens.d.ts +7 -0
  195. package/lib/typescript/engine/screens.d.ts.map +1 -1
  196. package/lib/typescript/interfaces/ComponentEvents.d.ts +2 -2
  197. package/lib/typescript/interfaces/options/animations.d.ts +40 -15
  198. package/lib/typescript/interfaces/options/animations.d.ts.map +1 -1
  199. package/lib/typescript/interfaces/options/bottomTabs.d.ts +2 -2
  200. package/lib/typescript/interfaces/options/buttons.d.ts +2 -2
  201. package/lib/typescript/interfaces/options/modals.d.ts +6 -7
  202. package/lib/typescript/interfaces/options/modals.d.ts.map +1 -1
  203. package/lib/typescript/interfaces/options/stack.d.ts +8 -3
  204. package/lib/typescript/interfaces/options/stack.d.ts.map +1 -1
  205. package/lib/typescript/interfaces/options/topBar.d.ts +14 -0
  206. package/lib/typescript/interfaces/options/topBar.d.ts.map +1 -1
  207. package/metro/acceptPlugin.js +57 -0
  208. package/metro/babelTransformer.js +45 -0
  209. package/metro/index.js +36 -0
  210. package/package.json +3 -1
  211. package/src/ARCHITECTURE.md +9 -3
  212. package/src/adapters/NativeANNTurboModule.ts +7 -0
  213. package/src/api/app/AppRegistry.ts +16 -2
  214. package/src/api/app/createNavigation.ts +198 -66
  215. package/src/api/events/navigationEvents.ts +9 -3
  216. package/src/api/index.ts +1 -0
  217. package/src/api/linking/linking.ts +22 -1
  218. package/src/api/screens/defineScreen.ts +49 -5
  219. package/src/api/screens/nativeScreens.ts +40 -4
  220. package/src/api/screens/registerScreens.tsx +185 -42
  221. package/src/api/theme/theme.ts +5 -0
  222. package/src/engine/commands.ts +21 -0
  223. package/src/engine/layout.ts +11 -2
  224. package/src/engine/nativeScreens.ts +10 -1
  225. package/src/engine/options.ts +6 -8
  226. package/src/engine/optionsChange.ts +107 -0
  227. package/src/engine/refresh.ts +97 -0
  228. package/src/engine/rememberedOptions.ts +70 -0
  229. package/src/engine/screens.tsx +24 -0
  230. package/src/interfaces/ComponentEvents.ts +2 -2
  231. package/src/interfaces/options/animations.ts +40 -15
  232. package/src/interfaces/options/bottomTabs.ts +2 -2
  233. package/src/interfaces/options/buttons.ts +2 -2
  234. package/src/interfaces/options/modals.ts +6 -7
  235. package/src/interfaces/options/stack.ts +8 -3
  236. package/src/interfaces/options/topBar.ts +14 -0
  237. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStub.kt +0 -31
  238. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMatrixAnimator.kt +0 -134
  239. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PlainViewAnimator.kt +0 -78
  240. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PropertyAnimatorCreator.kt +0 -33
  241. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ReactImageAnimator.kt +0 -57
  242. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewChangeAnimator.kt +0 -146
@@ -1,78 +0,0 @@
1
- package dev.apexnative.navigation.views.element.animators
2
-
3
- import android.animation.Animator
4
- import android.view.View
5
- import android.view.ViewOutlineProvider
6
- import com.facebook.react.uimanager.BackgroundStyleApplicator
7
- import com.facebook.react.uimanager.style.BorderRadiusProp
8
- import dev.apexnative.navigation.utils.borderRadius
9
- import dev.apexnative.navigation.views.animations.ValueInterpolation
10
- import dev.apexnative.navigation.views.element.TransitionLayer
11
- import kotlin.math.roundToInt
12
-
13
- /**
14
- * A shared React view without children moves itself: from where `from` is drawn to where it is drawn in its screen
15
- * ([FlightGeometry]); its size and corner radius by an outline that grows from `from`'s (at the scale it is drawn at)
16
- * to its own while it is laid out at the larger of the two sizes, unscaled and turned about the outline's middle; its
17
- * own radius taken off meanwhile and put back as it was; its background color from `from`'s to its own in Lab, ending
18
- * exactly on its own (`BackgroundStyleApplicator`). Main thread only.
19
- */
20
- internal class PlainViewAnimator(
21
- private val from: View,
22
- private val to: View,
23
- /** Where [to] was in its screen: what it flies to. */
24
- private val toStandIn: View?,
25
- private val layer: TransitionLayer,
26
- ) {
27
- /** The animator; none when [to] has no place in the layer. */
28
- fun create(): Animator? {
29
- val geometry = FlightGeometry.of(from, to, toStandIn, layer) ?: return null
30
- val fromRadius = from.borderRadius * geometry.from.scale
31
- val toRadius = to.borderRadius * geometry.to.scale
32
- val fromColor = BackgroundStyleApplicator.getBackgroundColor(from)
33
- val toColor = BackgroundStyleApplicator.getBackgroundColor(to)
34
- val ownRadius = BackgroundStyleApplicator.getBorderRadius(to, RADIUS)
35
- val outline = FlightOutline()
36
- val moved = MovedProperties(to)
37
- var savedProvider: ViewOutlineProvider? = null
38
- var savedClip = false
39
- val (width, height) = geometry.largest
40
- return MoveAnimator().apply {
41
- fun frame(time: Float) {
42
- val f = curve.getInterpolation(time)
43
- val at = geometry.at(f, time)
44
- outline.width = at.width.roundToInt()
45
- outline.height = at.height.roundToInt()
46
- outline.radius = ValueInterpolation.number(fromRadius, toRadius, f, time)
47
- moved.show(geometry, at, outline.width, outline.height)
48
- to.invalidateOutline()
49
- if (fromColor != toColor) {
50
- val color = ValueInterpolation.color(fromColor, toColor, f, time)
51
- BackgroundStyleApplicator.setBackgroundColor(to, color)
52
- }
53
- }
54
- onStart {
55
- savedProvider = to.outlineProvider
56
- savedClip = to.clipToOutline
57
- if (ownRadius != null) BackgroundStyleApplicator.setBorderRadius(to, RADIUS, null)
58
- to.outlineProvider = outline
59
- to.clipToOutline = true
60
- layer.place(to, geometry.toLeft, geometry.toTop, width, height)
61
- frame(0f)
62
- }
63
- onFrame { frame(it) }
64
- // A cancelled flight ends too: the view goes back whole.
65
- onEnd {
66
- if (fromColor != toColor) BackgroundStyleApplicator.setBackgroundColor(to, toColor)
67
- if (ownRadius != null) BackgroundStyleApplicator.setBorderRadius(to, RADIUS, ownRadius)
68
- to.outlineProvider = savedProvider
69
- to.clipToOutline = savedClip
70
- moved.end(geometry, landed) { w, h -> layer.place(to, geometry.toLeft, geometry.toTop, w, h) }
71
- }
72
- }
73
- }
74
-
75
- private companion object {
76
- val RADIUS = BorderRadiusProp.BORDER_RADIUS
77
- }
78
- }
@@ -1,33 +0,0 @@
1
- package dev.apexnative.navigation.views.element.animators
2
-
3
- import android.animation.Animator
4
- import android.view.View
5
- import dev.apexnative.navigation.options.SharedElementTransitionOptions
6
-
7
- /**
8
- * One animator of a shared element: how [from], on the screen that goes, becomes [to], on the screen that comes, when
9
- * both are of [type]. The core picks one by the views' classes (`SharedAnimatorFactory`) and runs it in the
10
- * transition's layer.
11
- */
12
- abstract class PropertyAnimatorCreator<T : View>(
13
- protected val from: View,
14
- protected val to: View,
15
- private val type: Class<T>,
16
- ) {
17
- /** Whether this animator takes part: both views are of its type and differ in what it animates. */
18
- fun shouldAnimate(): Boolean {
19
- if (!type.isInstance(from) || !type.isInstance(to)) return false
20
- val fromChild = type.cast(from) ?: return false
21
- val toChild = type.cast(to) ?: return false
22
- return shouldAnimateProperty(fromChild, toChild)
23
- }
24
-
25
- /** Whether [fromChild] and [toChild] differ in what this animator animates. */
26
- abstract fun shouldAnimateProperty(fromChild: T, toChild: T): Boolean
27
-
28
- /**
29
- * The animator of the pair for [options]; the core gives it the pair's duration, delay and curve (each animator
30
- * its own, never through a set around it).
31
- */
32
- abstract fun create(options: SharedElementTransitionOptions): Animator
33
- }
@@ -1,57 +0,0 @@
1
- package dev.apexnative.navigation.views.element.animators
2
-
3
- import android.animation.Animator
4
- import android.view.View
5
- import com.facebook.drawee.drawable.ScalingUtils
6
- import com.facebook.react.views.image.ReactImageView
7
- import dev.apexnative.navigation.views.element.TransitionLayer
8
- import kotlin.math.roundToInt
9
-
10
- /**
11
- * A shared React image: from where `from` is drawn to where it is drawn in its screen ([FlightGeometry]), laid out at
12
- * the size of each frame, unscaled and turned about its middle; its content by Fresco's scale type going from `from`'s
13
- * fit to its own (`ScalingUtils.InterpolatingScaleType`); Fresco's own fade off meanwhile. Everything goes back as it
14
- * was at the end. Main thread only.
15
- */
16
- internal class ReactImageAnimator(
17
- private val from: ReactImageView,
18
- private val to: ReactImageView,
19
- /** Where [to] was in its screen: what it flies to. */
20
- private val toStandIn: View?,
21
- private val layer: TransitionLayer,
22
- ) {
23
- /** The animator; none when [to] has no place in the layer or no hierarchy. */
24
- fun create(): Animator? {
25
- if (!from.hasHierarchy() || !to.hasHierarchy()) return null
26
- val geometry = FlightGeometry.of(from, to, toStandIn, layer) ?: return null
27
- val toType = to.hierarchy.actualImageScaleType ?: ScalingUtils.ScaleType.CENTER_CROP
28
- val fromType = from.hierarchy.actualImageScaleType ?: ScalingUtils.ScaleType.CENTER_CROP
29
- val scale = ScalingUtils.InterpolatingScaleType(fromType, toType)
30
- val moved = MovedProperties(to)
31
- var savedFade = 0
32
- return MoveAnimator().apply {
33
- fun frame(time: Float) {
34
- val f = curve.getInterpolation(time)
35
- val at = geometry.at(f, time)
36
- val width = at.width.roundToInt()
37
- val height = at.height.roundToInt()
38
- layer.place(to, geometry.toLeft, geometry.toTop, width, height)
39
- moved.show(geometry, at, width, height)
40
- scale.setValue(if (time >= 1f) 1f else f)
41
- to.invalidate()
42
- }
43
- onStart {
44
- savedFade = to.hierarchy.fadeDuration
45
- to.hierarchy.fadeDuration = 0
46
- to.hierarchy.setActualImageScaleType(scale)
47
- frame(0f)
48
- }
49
- onFrame { frame(it) }
50
- onEnd {
51
- to.hierarchy.setActualImageScaleType(toType)
52
- to.hierarchy.fadeDuration = savedFade
53
- moved.end(geometry, landed) { w, h -> layer.place(to, geometry.toLeft, geometry.toTop, w, h) }
54
- }
55
- }
56
- }
57
- }
@@ -1,146 +0,0 @@
1
- package dev.apexnative.navigation.views.element.animators
2
-
3
- import android.animation.Animator
4
- import android.graphics.Canvas
5
- import android.graphics.ColorFilter
6
- import android.graphics.Paint
7
- import android.graphics.Picture
8
- import android.graphics.PixelFormat
9
- import android.graphics.PorterDuff
10
- import android.graphics.PorterDuffXfermode
11
- import android.graphics.RectF
12
- import android.graphics.drawable.Drawable
13
- import android.view.View
14
- import android.view.ViewGroup
15
- import com.facebook.react.views.view.ReactViewGroup
16
- import dev.apexnative.navigation.options.SharedElementTransitionOptions
17
- import dev.apexnative.navigation.utils.borderRadius
18
- import kotlin.math.roundToInt
19
-
20
- // A view with children moves as two pictures of itself, as on iOS: of the view that goes away and of the one that
21
- // comes, each with its children. The copy goes from where the one is drawn — its center, its size at the scale it is
22
- // drawn at, its angle and corner radius — to where the other is drawn in its screen (FlightGeometry), the angle along
23
- // the shorter arc; both pictures fill it, and the picture of the destination shows over the other on the way. The
24
- // pictures are drawing commands: an avatar's letter grows sharp. They are drawn in the overlay of the transition layer
25
- // while `to` is hidden, and nothing else moves the pair. A view without children moves itself, its outline growing, as
26
- // before.
27
- class ViewChangeAnimator internal constructor(
28
- from: View,
29
- to: View,
30
- // Where `to` was in its screen: what the copy flies to.
31
- private val toStandIn: View?,
32
- ) : PropertyAnimatorCreator<ReactViewGroup>(from, to, ReactViewGroup::class.java) {
33
- private val pictures by lazy { pictures() }
34
-
35
- override fun shouldAnimateProperty(fromChild: ReactViewGroup, toChild: ReactViewGroup): Boolean =
36
- (fromChild.childCount > 0 || toChild.childCount > 0) && pictures != null
37
-
38
- override fun create(options: SharedElementTransitionOptions): Animator {
39
- val (start, end) = checkNotNull(pictures)
40
- val layer = to.parent as ViewGroup
41
- val drawable = ViewMorphDrawable(start, end)
42
- // Everything changes between the start and the end of the animation: a cancelled one ends too.
43
- return MoveAnimator().apply {
44
- onStart {
45
- drawable.setBounds(0, 0, layer.width, layer.height)
46
- layer.overlay.add(drawable)
47
- to.alpha = 0f
48
- }
49
- onFrame {
50
- drawable.update(it, curve.getInterpolation(it))
51
- layer.invalidate()
52
- }
53
- // A flight that landed where `to` shows only in its screen keeps its last picture: the transition takes the
54
- // layer away with it and shows `to` in its place.
55
- val holds = FlightEnd.holdsAtEnd(to, toStandIn, layer)
56
- onEnd {
57
- if (!holds || !landed) {
58
- layer.overlay.remove(drawable)
59
- layer.invalidate()
60
- to.alpha = end.alpha
61
- }
62
- }
63
- }
64
- }
65
-
66
- // `to` is in the transition layer already: the pictures are drawn in its coordinates. `from` is where it is drawn
67
- // on the screen, `to` where it is drawn once back in its screen.
68
- private fun pictures(): Pair<ViewPicture, ViewPicture>? {
69
- val layer = to.parent as? ViewGroup ?: return null
70
- val start = ViewPicture.of(from as ReactViewGroup, LayerPlace.of(from, layer)) ?: return null
71
- val end = ViewPicture.of(to as ReactViewGroup, LayerPlace.of(to, layer, toStandIn)) ?: return null
72
- return start to end
73
- }
74
- }
75
-
76
- // A view's picture, where it is drawn in the transition layer, its corner radius there and its opacity.
77
- private class ViewPicture(val picture: Picture, val end: FlightEnd, val radius: Float, val alpha: Float) {
78
- companion object {
79
- fun of(view: ReactViewGroup, place: LayerPlace): ViewPicture? {
80
- if (view.width <= 0 || view.height <= 0) return null
81
- val picture = recordPicture(view) ?: return null
82
- val end = place.end(view.width, view.height)
83
- return ViewPicture(picture, end, view.borderRadius * end.scale, view.alpha)
84
- }
85
- }
86
- }
87
-
88
- // The copy where the move has brought it: its center, size, angle and corner radius go from the start to the end along
89
- // the transition's curve, and so does the picture of the end over the picture of the start.
90
- private class ViewMorphDrawable(private val start: ViewPicture, private val end: ViewPicture) : Drawable() {
91
- private val flight = FlightGeometry(start.end, end.end, 0, 0)
92
- private var at = start.end
93
- private var progress = 0f
94
- private val rect = RectF()
95
- private val maskPaint = Paint(Paint.ANTI_ALIAS_FLAG)
96
- // What is drawn over the mask keeps only the mask's pixels: the corners stay smooth (a clip path on the hardware
97
- // canvas is not anti-aliased).
98
- private val contentPaint = Paint().apply { xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN) }
99
-
100
- /** The copy at [time] (the part of the time), [progress] the curve's value. */
101
- fun update(time: Float, progress: Float) {
102
- this.progress = progress
103
- at = flight.at(progress, time)
104
- }
105
-
106
- override fun draw(canvas: Canvas) {
107
- rect.set(-at.width / 2, -at.height / 2, at.width / 2, at.height / 2)
108
- if (rect.isEmpty) return
109
- val radius = lerp(start.radius, end.radius)
110
- // The copy turns about its center, mirrored where a view is.
111
- val count = canvas.save()
112
- canvas.translate(at.centerX, at.centerY)
113
- canvas.rotate(at.rotation)
114
- canvas.scale(at.mirrorX, at.mirrorY)
115
- canvas.saveLayer(rect, null)
116
- canvas.drawRoundRect(rect, radius, radius, maskPaint)
117
- canvas.saveLayer(rect, contentPaint)
118
- draw(canvas, start, start.alpha)
119
- draw(canvas, end, end.alpha * progress)
120
- canvas.restoreToCount(count)
121
- }
122
-
123
- // A picture fills the copy, as on iOS.
124
- private fun draw(canvas: Canvas, view: ViewPicture, shown: Float) {
125
- val alpha = (shown * 255).roundToInt().coerceIn(0, 255)
126
- if (alpha == 0) return
127
- val width = view.picture.width.toFloat()
128
- val height = view.picture.height.toFloat()
129
- val count = canvas.save()
130
- canvas.translate(rect.left, rect.top)
131
- canvas.scale(rect.width() / width, rect.height() / height)
132
- // The picture fades as a whole: its children and background don't show through each other.
133
- if (alpha < 255) canvas.saveLayerAlpha(0f, 0f, width, height, alpha)
134
- canvas.drawPicture(view.picture)
135
- canvas.restoreToCount(count)
136
- }
137
-
138
- private fun lerp(from: Float, to: Float) = from + (to - from) * progress
139
-
140
- override fun setAlpha(alpha: Int) = Unit
141
-
142
- override fun setColorFilter(colorFilter: ColorFilter?) = Unit
143
-
144
- @Deprecated("Deprecated in Java")
145
- override fun getOpacity(): Int = PixelFormat.TRANSLUCENT
146
- }