@react-native-ohos/react-native-reanimated 4.0.0-rc.1 → 4.0.2-beta.1

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 (235) hide show
  1. package/compatibility.json +161 -161
  2. package/harmony/reanimated/BuildProfile.ets +16 -16
  3. package/harmony/reanimated/build-profile.json5 +18 -18
  4. package/harmony/reanimated/hvigorfile.ts +4 -4
  5. package/harmony/reanimated/index.ets +4 -4
  6. package/harmony/reanimated/oh-package-lock.json5 +39 -0
  7. package/harmony/reanimated/oh-package.json5 +12 -12
  8. package/harmony/reanimated/src/main/cpp/CMakeLists.txt +65 -62
  9. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/AnimatedSensor/AnimatedSensorModule.cpp +81 -81
  10. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/AnimatedSensor/AnimatedSensorModule.h +46 -46
  11. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/InterpolatorRegistry.cpp +390 -390
  12. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/InterpolatorRegistry.h +16 -16
  13. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/definitions.h +30 -30
  14. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/filters/FilterOp.cpp +46 -46
  15. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/filters/FilterOp.h +23 -23
  16. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/Quaternion.cpp +53 -53
  17. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/Quaternion.h +21 -21
  18. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/TransformMatrix.cpp +166 -166
  19. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/TransformMatrix.h +71 -71
  20. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/TransformMatrix2D.cpp +368 -368
  21. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/TransformMatrix2D.h +53 -53
  22. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/TransformMatrix3D.cpp +594 -594
  23. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/TransformMatrix3D.h +67 -67
  24. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/TransformOp.cpp +52 -52
  25. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/TransformOp.h +26 -26
  26. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/vectors.cpp +156 -156
  27. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/vectors.h +76 -76
  28. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSAngle.cpp +94 -93
  29. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSAngle.h +33 -33
  30. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSBoolean.cpp +48 -48
  31. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSBoolean.h +31 -31
  32. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSColor.cpp +135 -135
  33. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSColor.h +61 -61
  34. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSDiscreteArray.cpp +100 -100
  35. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSDiscreteArray.h +45 -44
  36. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSKeyword.cpp +81 -81
  37. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSKeyword.h +53 -53
  38. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSLength.cpp +122 -122
  39. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSLength.h +38 -38
  40. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSNumber.cpp +82 -82
  41. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSNumber.h +63 -63
  42. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSValue.h +118 -118
  43. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSValueVariant.cpp +174 -174
  44. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSValueVariant.h +111 -111
  45. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/complex/CSSBoxShadow.cpp +196 -196
  46. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/complex/CSSBoxShadow.h +66 -66
  47. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/complex/CSSDropShadow.cpp +134 -134
  48. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/complex/CSSDropShadow.h +44 -44
  49. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/CSSAnimationConfig.cpp +174 -174
  50. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/CSSAnimationConfig.h +49 -49
  51. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/CSSKeyframesConfig.cpp +45 -45
  52. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/CSSKeyframesConfig.h +26 -26
  53. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/CSSTransitionConfig.cpp +90 -90
  54. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/CSSTransitionConfig.h +43 -43
  55. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/common.cpp +17 -17
  56. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/common.h +13 -13
  57. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/CSSAnimation.cpp +127 -127
  58. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/CSSAnimation.h +51 -51
  59. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/CSSTransition.cpp +145 -145
  60. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/CSSTransition.h +47 -47
  61. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/easing/EasingFunctions.cpp +69 -69
  62. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/easing/EasingFunctions.h +22 -22
  63. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/easing/cubicBezier.cpp +66 -66
  64. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/easing/cubicBezier.h +15 -15
  65. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/easing/linear.cpp +28 -28
  66. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/easing/linear.h +15 -15
  67. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/easing/steps.cpp +13 -13
  68. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/easing/steps.h +12 -12
  69. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/InterpolatorFactory.cpp +157 -157
  70. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/InterpolatorFactory.h +189 -189
  71. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/PropertyInterpolator.cpp +76 -76
  72. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/PropertyInterpolator.h +66 -66
  73. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/configs.h +20 -20
  74. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/FilterOperation.cpp +136 -136
  75. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/FilterOperation.h +40 -40
  76. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/FilterOperationInterpolator.cpp +38 -38
  77. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/FilterOperationInterpolator.h +24 -24
  78. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/FilterStyleInterpolator.cpp +58 -58
  79. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/FilterStyleInterpolator.h +24 -24
  80. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/blur.h +14 -14
  81. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/brightness.h +14 -14
  82. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/contrast.h +14 -14
  83. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/dropShadow.h +17 -17
  84. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/grayscale.h +14 -14
  85. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/hueRotate.h +14 -14
  86. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/invert.h +14 -14
  87. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/opacity.h +14 -14
  88. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/saturate.h +14 -14
  89. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/sepia.h +14 -14
  90. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/groups/ArrayPropertiesInterpolator.cpp +95 -95
  91. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/groups/ArrayPropertiesInterpolator.h +36 -36
  92. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/groups/GroupPropertiesInterpolator.cpp +41 -41
  93. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/groups/GroupPropertiesInterpolator.h +32 -32
  94. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/groups/RecordPropertiesInterpolator.cpp +99 -99
  95. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/groups/RecordPropertiesInterpolator.h +37 -37
  96. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/operations/OperationsStyleInterpolator.cpp +308 -308
  97. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/operations/OperationsStyleInterpolator.h +100 -100
  98. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/operations/StyleOperation.cpp +19 -19
  99. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/operations/StyleOperation.h +94 -94
  100. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/operations/StyleOperationInterpolator.cpp +18 -18
  101. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/operations/StyleOperationInterpolator.h +43 -43
  102. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/styles/AnimationStyleInterpolator.h +26 -26
  103. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/styles/TransitionStyleInterpolator.cpp +103 -103
  104. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/styles/TransitionStyleInterpolator.h +42 -42
  105. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/TransformOperation.cpp +224 -224
  106. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/TransformOperation.h +52 -52
  107. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/TransformOperationInterpolator.cpp +218 -218
  108. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/TransformOperationInterpolator.h +89 -89
  109. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/TransformsStyleInterpolator.cpp +149 -149
  110. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/TransformsStyleInterpolator.h +33 -33
  111. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/matrix.cpp +208 -208
  112. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/matrix.h +56 -56
  113. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/perspective.cpp +42 -42
  114. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/perspective.h +20 -20
  115. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/rotate.cpp +41 -41
  116. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/rotate.h +39 -39
  117. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/scale.cpp +28 -28
  118. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/scale.h +25 -25
  119. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/skew.cpp +14 -14
  120. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/skew.h +20 -20
  121. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/translate.cpp +39 -39
  122. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/translate.h +25 -25
  123. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/values/ResolvableValueInterpolator.cpp +47 -47
  124. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/values/ResolvableValueInterpolator.h +43 -43
  125. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/values/SimpleValueInterpolator.cpp +70 -70
  126. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/values/SimpleValueInterpolator.h +40 -40
  127. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/values/ValueInterpolator.cpp +146 -146
  128. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/values/ValueInterpolator.h +71 -71
  129. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/misc/ViewStylesRepository.cpp +155 -155
  130. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/misc/ViewStylesRepository.h +53 -53
  131. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/AnimationProgressProvider.cpp +170 -170
  132. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/AnimationProgressProvider.h +67 -67
  133. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/KeyframeProgressProvider.h +12 -12
  134. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/RawProgressProvider.cpp +41 -41
  135. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/RawProgressProvider.h +31 -31
  136. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/TransitionProgressProvider.cpp +193 -193
  137. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/TransitionProgressProvider.h +77 -77
  138. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/CSSAnimationsRegistry.cpp +340 -340
  139. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/CSSAnimationsRegistry.h +80 -80
  140. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/CSSKeyframesRegistry.cpp +45 -45
  141. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/CSSKeyframesRegistry.h +29 -29
  142. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/CSSTransitionsRegistry.cpp +167 -167
  143. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/CSSTransitionsRegistry.h +51 -51
  144. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/StaticPropsRegistry.cpp +61 -61
  145. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/StaticPropsRegistry.h +33 -33
  146. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGBrush.cpp +80 -80
  147. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGBrush.h +39 -39
  148. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGLength.cpp +93 -93
  149. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGLength.h +36 -36
  150. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGStrokeDashArray.cpp +111 -110
  151. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGStrokeDashArray.h +33 -33
  152. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/DelayedItemsManager.cpp +75 -75
  153. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/DelayedItemsManager.h +45 -45
  154. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/algorithms.cpp +12 -12
  155. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/algorithms.h +10 -10
  156. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/interpolators.cpp +36 -36
  157. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/interpolators.h +23 -23
  158. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/props.cpp +149 -149
  159. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/props.h +32 -32
  160. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.cpp +113 -113
  161. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.h +49 -49
  162. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedCommitShadowNode.h +46 -46
  163. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedMountHook.cpp +56 -56
  164. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedMountHook.h +37 -37
  165. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ShadowTreeCloner.cpp +104 -104
  166. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ShadowTreeCloner.h +22 -22
  167. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.cpp +72 -72
  168. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.h +25 -25
  169. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.cpp +160 -160
  170. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.h +71 -71
  171. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.cpp +161 -161
  172. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.h +65 -65
  173. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationType.h +11 -11
  174. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsManager.cpp +137 -137
  175. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsManager.h +82 -82
  176. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.cpp +79 -79
  177. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.h +81 -81
  178. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp +864 -864
  179. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h +214 -214
  180. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.cpp +897 -897
  181. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.h +220 -220
  182. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.cpp +31 -31
  183. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.h +146 -146
  184. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/PropsDiffer.cpp +456 -456
  185. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/PropsDiffer.h +102 -102
  186. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/SharedTransitions.cpp +544 -544
  187. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/PropValueProcessor.cpp +119 -119
  188. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/PropValueProcessor.h +39 -39
  189. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +1380 -1376
  190. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +230 -228
  191. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.cpp +183 -183
  192. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.h +93 -93
  193. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.cpp +54 -54
  194. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.h +28 -28
  195. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.cpp +58 -58
  196. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.h +31 -31
  197. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/FeatureFlags.cpp +18 -18
  198. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/FeatureFlags.h +44 -44
  199. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/PlatformDepMethodsHolder.h +67 -67
  200. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/ReanimatedSystraceSection.h +114 -114
  201. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/ReanimatedVersion.cpp +46 -46
  202. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/ReanimatedVersion.h +18 -18
  203. package/harmony/reanimated/src/main/cpp/ReanimatedModule.cpp +233 -230
  204. package/harmony/reanimated/src/main/cpp/ReanimatedModule.h +23 -23
  205. package/harmony/reanimated/src/main/cpp/ReanimatedNodesManager.cpp +56 -56
  206. package/harmony/reanimated/src/main/cpp/ReanimatedNodesManager.h +30 -30
  207. package/harmony/reanimated/src/main/cpp/ReanimatedPackage.cpp +44 -44
  208. package/harmony/reanimated/src/main/cpp/ReanimatedPackage.h +16 -16
  209. package/harmony/reanimated/src/main/cpp/ReanimatedSensor.cpp +265 -265
  210. package/harmony/reanimated/src/main/cpp/ReanimatedSensor.h +36 -36
  211. package/harmony/reanimated/src/main/cpp/ReanimatedSensorContainer.cpp +35 -35
  212. package/harmony/reanimated/src/main/cpp/ReanimatedSensorContainer.h +23 -23
  213. package/harmony/reanimated/src/main/cpp/ReanimatedUIScheduler.cpp +23 -23
  214. package/harmony/reanimated/src/main/cpp/ReanimatedUIScheduler.h +19 -19
  215. package/harmony/reanimated/src/main/cpp/TransformParser.h +93 -93
  216. package/harmony/reanimated/src/main/ets/AnimationManager.ts +60 -60
  217. package/harmony/reanimated/src/main/ets/ReanimatedModule.ts +51 -51
  218. package/harmony/reanimated/src/main/ets/ReanimatedPackage.ts +25 -25
  219. package/harmony/reanimated/src/main/module.json5 +12 -12
  220. package/harmony/reanimated/src/main/resources/base/element/color.json +7 -7
  221. package/harmony/reanimated/src/main/resources/base/element/string.json +15 -15
  222. package/harmony/reanimated/src/main/resources/base/profile/main_pages.json +5 -5
  223. package/harmony/reanimated/src/main/resources/en_US/element/string.json +15 -15
  224. package/harmony/reanimated/src/main/resources/zh_CN/element/string.json +15 -15
  225. package/harmony/reanimated/ts.ts +6 -6
  226. package/harmony/reanimated.har +0 -0
  227. package/package.json +70 -68
  228. package/scripts/deploy.js +191 -191
  229. package/scripts/set-reanimated-version.js +37 -37
  230. package/scripts/update-version.js +119 -119
  231. package/scripts/validate-react-native-version.js +46 -46
  232. package/scripts/validate-worklets-build.js +17 -17
  233. package/scripts/validate-worklets-version.js +84 -79
  234. package/scripts/worklets-version.json +4 -4
  235. package/src/index.ts +9 -9
@@ -1,1376 +1,1380 @@
1
- #include <jsi/jsi.h>
2
- #include <reanimated/NativeModules/PropValueProcessor.h>
3
- #include <reanimated/NativeModules/ReanimatedModuleProxy.h>
4
- #include <reanimated/RuntimeDecorators/UIRuntimeDecorator.h>
5
- #include <reanimated/Tools/FeatureFlags.h>
6
- #include <reanimated/Tools/ReanimatedSystraceSection.h>
7
-
8
- #include <worklets/Registries/EventHandlerRegistry.h>
9
- #include <worklets/SharedItems/Serializable.h>
10
- #include <worklets/Tools/WorkletEventHandler.h>
11
-
12
- #ifdef __ANDROID__
13
- #include <fbjni/fbjni.h>
14
- #endif // __ANDROID__
15
-
16
- #include <react/renderer/scheduler/Scheduler.h>
17
- #include <react/renderer/uimanager/UIManagerBinding.h>
18
- #include <reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h>
19
- #include <reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.h>
20
-
21
- #include <functional>
22
- #include <iomanip>
23
- #include <memory>
24
- #include <sstream>
25
- #include <string>
26
- #include <unordered_map>
27
- #include <unordered_set>
28
- #include <utility>
29
- #include <vector>
30
-
31
- namespace reanimated {
32
-
33
- #if REACT_NATIVE_MINOR_VERSION >= 81
34
- static inline std::shared_ptr<const ShadowNode> shadowNodeFromValue(
35
- jsi::Runtime &rt,
36
- const jsi::Value &shadowNodeWrapper) {
37
- return Bridging<std::shared_ptr<const ShadowNode>>::fromJs(rt, shadowNodeWrapper);
38
- }
39
- #endif
40
-
41
- ReanimatedModuleProxy::ReanimatedModuleProxy(
42
- const std::shared_ptr<WorkletsModuleProxy> &workletsModuleProxy,
43
- jsi::Runtime &rnRuntime,
44
- const std::shared_ptr<CallInvoker> &jsCallInvoker,
45
- const PlatformDepMethodsHolder &platformDepMethodsHolder,
46
- const bool isReducedMotion)
47
- : ReanimatedModuleProxySpec(jsCallInvoker),
48
- isReducedMotion_(isReducedMotion),
49
- workletsModuleProxy_(workletsModuleProxy),
50
- eventHandlerRegistry_(std::make_unique<EventHandlerRegistry>()),
51
- requestRender_(platformDepMethodsHolder.requestRender),
52
- animatedSensorModule_(platformDepMethodsHolder),
53
- jsLogger_(std::make_shared<JSLogger>(workletsModuleProxy->getJSScheduler())),
54
- layoutAnimationsManager_(std::make_shared<LayoutAnimationsManager>(jsLogger_)),
55
- getAnimationTimestamp_(platformDepMethodsHolder.getAnimationTimestamp),
56
- #ifdef __APPLE__
57
- forceScreenSnapshot_(platformDepMethodsHolder.forceScreenSnapshotFunction),
58
- #endif
59
- animatedPropsRegistry_(std::make_shared<AnimatedPropsRegistry>()),
60
- staticPropsRegistry_(std::make_shared<StaticPropsRegistry>()),
61
- updatesRegistryManager_(std::make_shared<UpdatesRegistryManager>(staticPropsRegistry_)),
62
- viewStylesRepository_(std::make_shared<ViewStylesRepository>(staticPropsRegistry_, animatedPropsRegistry_)),
63
- cssAnimationKeyframesRegistry_(std::make_shared<CSSKeyframesRegistry>(viewStylesRepository_)),
64
- cssAnimationsRegistry_(std::make_shared<CSSAnimationsRegistry>()),
65
- cssTransitionsRegistry_(std::make_shared<CSSTransitionsRegistry>(staticPropsRegistry_, getAnimationTimestamp_)),
66
- synchronouslyUpdateUIPropsFunction_(platformDepMethodsHolder.synchronouslyUpdateUIPropsFunction),
67
- #ifdef ANDROID
68
- filterUnmountedTagsFunction_(platformDepMethodsHolder.filterUnmountedTagsFunction),
69
- #endif // ANDROID
70
- subscribeForKeyboardEventsFunction_(platformDepMethodsHolder.subscribeForKeyboardEvents),
71
- unsubscribeFromKeyboardEventsFunction_(platformDepMethodsHolder.unsubscribeFromKeyboardEvents) {
72
- auto lock = updatesRegistryManager_->lock();
73
- // Add registries in order of their priority (from the lowest to the
74
- // highest)
75
- // CSS transitions should be overriden by animated style animations;
76
- // animated style animations should be overriden by CSS animations
77
- updatesRegistryManager_->addRegistry(cssTransitionsRegistry_);
78
- updatesRegistryManager_->addRegistry(animatedPropsRegistry_);
79
- updatesRegistryManager_->addRegistry(cssAnimationsRegistry_);
80
- }
81
-
82
- void ReanimatedModuleProxy::init(const PlatformDepMethodsHolder &platformDepMethodsHolder) {
83
- auto onRenderCallback = [weakThis = weak_from_this()](const double timestampMs) {
84
- auto strongThis = weakThis.lock();
85
- if (!strongThis) {
86
- return;
87
- }
88
-
89
- strongThis->renderRequested_ = false;
90
- strongThis->onRender(timestampMs);
91
- };
92
- onRenderCallback_ = std::move(onRenderCallback);
93
-
94
- auto updateProps = [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &operations) {
95
- auto strongThis = weakThis.lock();
96
- if (!strongThis) {
97
- return;
98
- }
99
-
100
- const auto timestamp = strongThis->getAnimationTimestamp_();
101
- strongThis->animatedPropsRegistry_->update(rt, operations, timestamp);
102
- };
103
-
104
- auto measure = [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &shadowNodeValue) -> jsi::Value {
105
- auto strongThis = weakThis.lock();
106
- if (!strongThis) {
107
- return jsi::Value::undefined();
108
- }
109
- return strongThis->measure(rt, shadowNodeValue);
110
- };
111
-
112
- auto dispatchCommand = [weakThis = weak_from_this()](
113
- jsi::Runtime &rt,
114
- const jsi::Value &shadowNodeValue,
115
- const jsi::Value &commandNameValue,
116
- const jsi::Value &argsValue) {
117
- auto strongThis = weakThis.lock();
118
- if (!strongThis) {
119
- return;
120
- }
121
-
122
- strongThis->dispatchCommand(rt, shadowNodeValue, commandNameValue, argsValue);
123
- };
124
- ProgressLayoutAnimationFunction progressLayoutAnimation =
125
- [weakThis = weak_from_this()](jsi::Runtime &rt, int tag, const jsi::Object &newStyle) {
126
- auto strongThis = weakThis.lock();
127
- if (!strongThis) {
128
- return;
129
- }
130
- auto surfaceId = strongThis->layoutAnimationsProxy_->progressLayoutAnimation(tag, newStyle);
131
- if (!surfaceId) {
132
- return;
133
- }
134
- strongThis->layoutAnimationFlushRequests_.insert(*surfaceId);
135
- };
136
-
137
- auto requestLayoutAnimationRender = [weakThis = weak_from_this()](double) {
138
- auto strongThis = weakThis.lock();
139
- if (!strongThis) {
140
- return;
141
- }
142
- strongThis->layoutAnimationRenderRequested_ = false;
143
- };
144
-
145
- EndLayoutAnimationFunction endLayoutAnimation = [weakThis = weak_from_this(), requestLayoutAnimationRender](
146
- int tag, bool shouldRemove) {
147
- auto strongThis = weakThis.lock();
148
- if (!strongThis) {
149
- return;
150
- }
151
-
152
- auto surfaceId = strongThis->layoutAnimationsProxy_->endLayoutAnimation(tag, shouldRemove);
153
-
154
- if (!strongThis->layoutAnimationRenderRequested_) {
155
- strongThis->layoutAnimationRenderRequested_ = true;
156
- // if an animation has duration 0, performOperations would not get
157
- // called for it so we call requestRender to have it called in the
158
- // next frame
159
- strongThis->requestRender_(requestLayoutAnimationRender);
160
- }
161
-
162
- if (!surfaceId) {
163
- return;
164
- }
165
- strongThis->layoutAnimationFlushRequests_.insert(*surfaceId);
166
- };
167
-
168
- auto obtainProp = [weakThis = weak_from_this()](
169
- jsi::Runtime &rt, const jsi::Value &shadowNodeWrapper, const jsi::Value &propName) {
170
- auto strongThis = weakThis.lock();
171
- if (!strongThis) {
172
- return jsi::String::createFromUtf8(rt, "");
173
- }
174
-
175
- return strongThis->obtainProp(rt, shadowNodeWrapper, propName);
176
- };
177
-
178
- jsi::Runtime &uiRuntime = workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
179
- UIRuntimeDecorator::decorate(
180
- uiRuntime,
181
- obtainProp,
182
- updateProps,
183
- measure,
184
- dispatchCommand,
185
- platformDepMethodsHolder.getAnimationTimestamp,
186
- platformDepMethodsHolder.setGestureStateFunction,
187
- progressLayoutAnimation,
188
- endLayoutAnimation,
189
- platformDepMethodsHolder.maybeFlushUIUpdatesQueueFunction);
190
- }
191
-
192
- ReanimatedModuleProxy::~ReanimatedModuleProxy() {
193
- // event handler registry and frame callbacks store some JSI values from UI
194
- // runtime, so they have to go away before we tear down the runtime
195
- eventHandlerRegistry_.reset();
196
- }
197
-
198
- jsi::Value ReanimatedModuleProxy::registerEventHandler(
199
- jsi::Runtime &rt,
200
- const jsi::Value &worklet,
201
- const jsi::Value &eventName,
202
- const jsi::Value &emitterReactTag) {
203
- static uint64_t NEXT_EVENT_HANDLER_ID = 1;
204
-
205
- uint64_t newRegistrationId = NEXT_EVENT_HANDLER_ID++;
206
- auto eventNameStr = eventName.asString(rt).utf8(rt);
207
- auto handlerSerializable = extractSerializableOrThrow<SerializableWorklet>(
208
- rt, worklet, "[Reanimated] Event handler must be a serializable worklet.");
209
- int emitterReactTagInt = emitterReactTag.asNumber();
210
-
211
- workletsModuleProxy_->getUIScheduler()->scheduleOnUI([=, weakThis = weak_from_this()]() {
212
- auto strongThis = weakThis.lock();
213
- if (!strongThis) {
214
- return;
215
- }
216
- auto handler =
217
- std::make_shared<WorkletEventHandler>(newRegistrationId, eventNameStr, emitterReactTagInt, handlerSerializable);
218
- strongThis->eventHandlerRegistry_->registerEventHandler(handler);
219
- });
220
-
221
- return jsi::Value(static_cast<double>(newRegistrationId));
222
- }
223
-
224
- void ReanimatedModuleProxy::unregisterEventHandler(jsi::Runtime &, const jsi::Value &registrationId) {
225
- uint64_t id = registrationId.asNumber();
226
- workletsModuleProxy_->getUIScheduler()->scheduleOnUI([=, weakThis = weak_from_this()]() {
227
- auto strongThis = weakThis.lock();
228
- if (!strongThis) {
229
- return;
230
- }
231
- strongThis->eventHandlerRegistry_->unregisterEventHandler(id);
232
- });
233
- }
234
-
235
- std::string ReanimatedModuleProxy::obtainPropFromShadowNode(
236
- jsi::Runtime &rt,
237
- const std::string &propName,
238
- const std::shared_ptr<const ShadowNode> &shadowNode) {
239
- auto newestCloneOfShadowNode = uiManager_->getNewestCloneOfShadowNode(*shadowNode);
240
-
241
- return PropValueProcessor::processPropValue(propName, newestCloneOfShadowNode, rt);
242
- }
243
-
244
- jsi::Value ReanimatedModuleProxy::getViewProp(
245
- jsi::Runtime &rnRuntime,
246
- const jsi::Value &shadowNodeWrapper,
247
- const jsi::Value &propName,
248
- const jsi::Value &callback) {
249
- const auto propNameStr = propName.asString(rnRuntime).utf8(rnRuntime);
250
- const auto funPtr = std::make_shared<jsi::Function>(callback.getObject(rnRuntime).asFunction(rnRuntime));
251
- const auto shadowNode = shadowNodeFromValue(rnRuntime, shadowNodeWrapper);
252
- workletsModuleProxy_->getUIScheduler()->scheduleOnUI([=, weakThis = weak_from_this()]() {
253
- auto strongThis = weakThis.lock();
254
- if (!strongThis) {
255
- return;
256
- }
257
- jsi::Runtime &uiRuntime = strongThis->workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
258
- const auto resultStr = strongThis->obtainPropFromShadowNode(uiRuntime, propNameStr, shadowNode);
259
-
260
- strongThis->workletsModuleProxy_->getJSScheduler()->scheduleOnJS([=](jsi::Runtime &rnRuntime) {
261
- const auto resultValue = jsi::String::createFromUtf8(rnRuntime, resultStr);
262
- funPtr->call(rnRuntime, resultValue);
263
- });
264
- });
265
- return jsi::Value::undefined();
266
- }
267
-
268
- jsi::Value ReanimatedModuleProxy::getStaticFeatureFlag(jsi::Runtime &rt, const jsi::Value &name) {
269
- return reanimated::StaticFeatureFlags::getFlag(name.asString(rt).utf8(rt));
270
- }
271
-
272
- jsi::Value
273
- ReanimatedModuleProxy::setDynamicFeatureFlag(jsi::Runtime &rt, const jsi::Value &name, const jsi::Value &value) {
274
- reanimated::DynamicFeatureFlags::setFlag(name.asString(rt).utf8(rt), value.asBool());
275
- return jsi::Value::undefined();
276
- }
277
-
278
- jsi::Value ReanimatedModuleProxy::configureLayoutAnimationBatch(
279
- jsi::Runtime &rt,
280
- const jsi::Value &layoutAnimationsBatch) {
281
- auto array = layoutAnimationsBatch.asObject(rt).asArray(rt);
282
- size_t length = array.size(rt);
283
- std::vector<LayoutAnimationConfig> batch(length);
284
- for (int i = 0; i < length; i++) {
285
- auto item = array.getValueAtIndex(rt, i).asObject(rt);
286
- auto &batchItem = batch[i];
287
- batchItem.tag = item.getProperty(rt, "viewTag").asNumber();
288
- batchItem.type = static_cast<LayoutAnimationType>(item.getProperty(rt, "type").asNumber());
289
- auto config = item.getProperty(rt, "config");
290
- if (config.isUndefined()) {
291
- batchItem.config = nullptr;
292
- } else {
293
- batchItem.config = extractSerializableOrThrow<SerializableObject>(
294
- rt, config, "[Reanimated] Layout animation config must be an object.");
295
- }
296
- auto sharedTag = item.getProperty(rt, "sharedTransitionTag");
297
- if (!sharedTag.isUndefined()) {
298
- batchItem.sharedTransitionTag = sharedTag.asString(rt).utf8(rt);
299
- }
300
- }
301
- layoutAnimationsManager_->configureAnimationBatch(batch);
302
- return jsi::Value::undefined();
303
- }
304
-
305
- void ReanimatedModuleProxy::setShouldAnimateExiting(
306
- jsi::Runtime &rt,
307
- const jsi::Value &viewTag,
308
- const jsi::Value &shouldAnimate) {
309
- layoutAnimationsManager_->setShouldAnimateExiting(viewTag.asNumber(), shouldAnimate.getBool());
310
- }
311
-
312
- bool ReanimatedModuleProxy::isAnyHandlerWaitingForEvent(const std::string &eventName, const int emitterReactTag) {
313
- return eventHandlerRegistry_->isAnyHandlerWaitingForEvent(eventName, emitterReactTag);
314
- }
315
-
316
- void ReanimatedModuleProxy::maybeRequestRender() {
317
- if (!renderRequested_) {
318
- renderRequested_ = true;
319
- requestRender_(onRenderCallback_);
320
- }
321
- }
322
-
323
- void ReanimatedModuleProxy::onRender(double timestampMs) {
324
- ReanimatedSystraceSection s("ReanimatedModuleProxy::onRender");
325
- // NOOP
326
- }
327
-
328
- jsi::Value ReanimatedModuleProxy::registerSensor(
329
- jsi::Runtime &rt,
330
- const jsi::Value &sensorType,
331
- const jsi::Value &interval,
332
- const jsi::Value &iosReferenceFrame,
333
- const jsi::Value &sensorDataHandler) {
334
- return animatedSensorModule_.registerSensor(
335
- rt, workletsModuleProxy_->getUIWorkletRuntime(), sensorType, interval, iosReferenceFrame, sensorDataHandler);
336
- }
337
-
338
- void ReanimatedModuleProxy::unregisterSensor(jsi::Runtime &, const jsi::Value &sensorId) {
339
- animatedSensorModule_.unregisterSensor(sensorId);
340
- }
341
-
342
- void ReanimatedModuleProxy::cleanupSensors() {
343
- animatedSensorModule_.unregisterAllSensors();
344
- }
345
-
346
- void ReanimatedModuleProxy::setViewStyle(jsi::Runtime &rt, const jsi::Value &viewTag, const jsi::Value &viewStyle) {
347
- const auto tag = viewTag.asNumber();
348
- staticPropsRegistry_->set(rt, tag, viewStyle);
349
- if (staticPropsRegistry_->hasObservers(tag)) {
350
- maybeRunCSSLoop();
351
- }
352
- }
353
-
354
- void ReanimatedModuleProxy::markNodeAsRemovable(jsi::Runtime &rt, const jsi::Value &shadowNodeWrapper) {
355
- auto lock = updatesRegistryManager_->lock();
356
- auto shadowNode = shadowNodeFromValue(rt, shadowNodeWrapper);
357
- updatesRegistryManager_->markNodeAsRemovable(shadowNode);
358
- }
359
-
360
- void ReanimatedModuleProxy::unmarkNodeAsRemovable(jsi::Runtime &rt, const jsi::Value &viewTag) {
361
- auto lock = updatesRegistryManager_->lock();
362
- updatesRegistryManager_->unmarkNodeAsRemovable(viewTag.asNumber());
363
- }
364
-
365
- void ReanimatedModuleProxy::registerCSSKeyframes(
366
- jsi::Runtime &rt,
367
- const jsi::Value &animationName,
368
- const jsi::Value &viewName,
369
- const jsi::Value &keyframesConfig) {
370
- // Convert react view name to Fabric component name
371
- const auto componentName = componentNameByReactViewName(viewName.asString(rt).utf8(rt));
372
- cssAnimationKeyframesRegistry_->set(
373
- animationName.asString(rt).utf8(rt),
374
- componentName,
375
- parseCSSAnimationKeyframesConfig(rt, keyframesConfig, componentName, viewStylesRepository_));
376
- }
377
-
378
- void ReanimatedModuleProxy::unregisterCSSKeyframes(
379
- jsi::Runtime &rt,
380
- const jsi::Value &animationName,
381
- const jsi::Value &viewName) {
382
- cssAnimationKeyframesRegistry_->remove(
383
- animationName.asString(rt).utf8(rt), componentNameByReactViewName(viewName.asString(rt).utf8(rt)));
384
- }
385
-
386
- void ReanimatedModuleProxy::applyCSSAnimations(
387
- jsi::Runtime &rt,
388
- const jsi::Value &shadowNodeWrapper,
389
- const jsi::Value &animationUpdates) {
390
- auto shadowNode = shadowNodeFromValue(rt, shadowNodeWrapper);
391
- const auto timestamp = getCssTimestamp();
392
- const auto updates = parseCSSAnimationUpdates(rt, animationUpdates);
393
-
394
- CSSAnimationsMap newAnimations;
395
-
396
- if (!updates.newAnimationSettings.empty()) {
397
- // animationNames always exists when newAnimationSettings is not empty
398
- const auto animationNames = updates.animationNames.value();
399
- const auto animationNamesCount = animationNames.size();
400
-
401
- for (const auto &[index, settings] : updates.newAnimationSettings) {
402
- if (index >= animationNamesCount) {
403
- throw std::invalid_argument("[Reanimated] index is out of bounds of animationNames");
404
- }
405
-
406
- const auto &animationName = animationNames[index];
407
- const auto &keyframesConfig = cssAnimationKeyframesRegistry_->get(animationName, shadowNode->getComponentName());
408
-
409
- newAnimations.emplace(
410
- index, std::make_shared<CSSAnimation>(rt, shadowNode, animationName, keyframesConfig, settings, timestamp));
411
- }
412
- }
413
-
414
- {
415
- auto lock = cssAnimationsRegistry_->lock();
416
- cssAnimationsRegistry_->apply(
417
- rt, shadowNode, updates.animationNames, newAnimations, updates.settingsUpdates, timestamp);
418
- }
419
-
420
- maybeRunCSSLoop();
421
- }
422
-
423
- void ReanimatedModuleProxy::unregisterCSSAnimations(const jsi::Value &viewTag) {
424
- auto lock = cssAnimationsRegistry_->lock();
425
- cssAnimationsRegistry_->remove(viewTag.asNumber());
426
- }
427
-
428
- void ReanimatedModuleProxy::registerCSSTransition(
429
- jsi::Runtime &rt,
430
- const jsi::Value &shadowNodeWrapper,
431
- const jsi::Value &transitionConfig) {
432
- auto shadowNode = shadowNodeFromValue(rt, shadowNodeWrapper);
433
-
434
- auto transition = std::make_shared<CSSTransition>(
435
- std::move(shadowNode), parseCSSTransitionConfig(rt, transitionConfig), viewStylesRepository_);
436
-
437
- {
438
- auto lock = cssTransitionsRegistry_->lock();
439
- cssTransitionsRegistry_->add(transition);
440
- }
441
- maybeRunCSSLoop();
442
- }
443
-
444
- void ReanimatedModuleProxy::updateCSSTransition(
445
- jsi::Runtime &rt,
446
- const jsi::Value &viewTag,
447
- const jsi::Value &configUpdates) {
448
- auto lock = cssTransitionsRegistry_->lock();
449
- cssTransitionsRegistry_->updateSettings(viewTag.asNumber(), parsePartialCSSTransitionConfig(rt, configUpdates));
450
- maybeRunCSSLoop();
451
- }
452
-
453
- void ReanimatedModuleProxy::unregisterCSSTransition(jsi::Runtime &rt, const jsi::Value &viewTag) {
454
- auto lock = cssTransitionsRegistry_->lock();
455
- cssTransitionsRegistry_->remove(viewTag.asNumber());
456
- }
457
-
458
- jsi::Value ReanimatedModuleProxy::getSettledUpdates(jsi::Runtime &rt) {
459
- react_native_assert(
460
- StaticFeatureFlags::getFlag("FORCE_REACT_RENDER_FOR_SETTLED_ANIMATIONS") &&
461
- "getSettledUpdates requires FORCE_REACT_RENDER_FOR_SETTLED_ANIMATIONS static feature flag to be enabled");
462
-
463
- // TODO(future): use unified timestamp
464
- const auto currentTimestamp = getAnimationTimestamp_();
465
-
466
- const auto lock = animatedPropsRegistry_->lock();
467
-
468
- // TODO: fix bug when threshold difference is smaller than 1 second
469
- // TODO(future): flush updates from CSS animations and CSS transitions registries
470
- animatedPropsRegistry_->removeUpdatesOlderThanTimestamp(currentTimestamp - 2000); // 2 seconds
471
-
472
- // TODO(future): find a better way to obtain timestamp for removing updates
473
- // TODO(future): move removing old updates to separate method
474
- return animatedPropsRegistry_->getUpdatesOlderThanTimestamp(rt, currentTimestamp - 1000); // 1 second
475
- }
476
-
477
- bool ReanimatedModuleProxy::handleEvent(
478
- const std::string &eventName,
479
- const int emitterReactTag,
480
- const jsi::Value &payload,
481
- double currentTime) {
482
- ReanimatedSystraceSection s("ReanimatedModuleProxy::handleEvent");
483
-
484
- eventHandlerRegistry_->processEvent(
485
- workletsModuleProxy_->getUIWorkletRuntime(), currentTime, eventName, emitterReactTag, payload);
486
-
487
- // TODO: return true if Reanimated successfully handled the event
488
- // to avoid sending it to JavaScript
489
- return false;
490
- }
491
-
492
- bool ReanimatedModuleProxy::handleRawEvent(const RawEvent &rawEvent, double currentTime) {
493
- ReanimatedSystraceSection s("ReanimatedModuleProxy::handleRawEvent");
494
-
495
- const EventTarget *eventTarget = rawEvent.eventTarget.get();
496
- if (eventTarget == nullptr) {
497
- // after app reload scrollView is unmounted and its content offset is set
498
- // to 0 and view is thrown into recycle pool setting content offset
499
- // triggers scroll event eventTarget is null though, because it's
500
- // unmounting we can just ignore this event, because it's an event on
501
- // unmounted component
502
- return false;
503
- }
504
-
505
- int tag = eventTarget->getTag();
506
- auto eventType = rawEvent.type;
507
- if (eventType.rfind("top", 0) == 0) {
508
- eventType = "on" + eventType.substr(3);
509
- }
510
-
511
- if constexpr (StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS")) {
512
- if (eventType == "onTransitionProgress") {
513
- jsi::Runtime &rt = workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
514
- const auto &eventPayload = rawEvent.eventPayload;
515
- jsi::Object payload = eventPayload->asJSIValue(rt).asObject(rt);
516
- auto progress = payload.getProperty(rt, "progress").asNumber();
517
- auto closing = static_cast<bool>(payload.getProperty(rt, "closing").asNumber());
518
- auto goingForward = static_cast<bool>(payload.getProperty(rt, "goingForward").asNumber());
519
-
520
- if (!layoutAnimationsProxy_) {
521
- return false;
522
- }
523
- auto surfaceId = layoutAnimationsProxy_->onTransitionProgress(tag, progress, closing, goingForward);
524
- if (!surfaceId) {
525
- return false;
526
- }
527
- // TODO (future): enumerate -> visit
528
- uiManager_->getShadowTreeRegistry().enumerate(
529
- [](const ShadowTree &shadowTree, bool &) { shadowTree.notifyDelegatesOfUpdates(); });
530
- return false;
531
- } else if (eventType == "onGestureCancel") {
532
- if (!layoutAnimationsProxy_) {
533
- return false;
534
- }
535
- auto surfaceId = layoutAnimationsProxy_->onGestureCancel();
536
- if (!surfaceId) {
537
- return false;
538
- }
539
- // TODO (future): enumerate -> visit
540
- uiManager_->getShadowTreeRegistry().enumerate(
541
- [](const ShadowTree &shadowTree, bool &) { shadowTree.notifyDelegatesOfUpdates(); });
542
- return false;
543
- }
544
- }
545
-
546
- if (!isAnyHandlerWaitingForEvent(eventType, tag)) {
547
- return false;
548
- }
549
-
550
- jsi::Runtime &rt = workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
551
- const auto &eventPayload = rawEvent.eventPayload;
552
- jsi::Value payload = eventPayload->asJSIValue(rt);
553
-
554
- auto res = handleEvent(eventType, tag, payload, currentTime);
555
- // TODO: we should call performOperations conditionally if event is handled
556
- // (res == true), but for now handleEvent always returns false. Thankfully,
557
- // performOperations does not trigger a lot of code if there is nothing to
558
- // be done so this is fine for now.
559
- performOperations(true);
560
- return res;
561
- }
562
-
563
- void ReanimatedModuleProxy::cssLoopCallback(const double /*timestampMs*/) {
564
- shouldUpdateCssAnimations_ = true;
565
- if (cssAnimationsRegistry_->hasUpdates() || cssTransitionsRegistry_->hasUpdates()
566
- #ifdef ANDROID
567
- || updatesRegistryManager_->hasPropsToRevert()
568
- #endif // ANDROID
569
- ) {
570
- requestRender_([weakThis = weak_from_this()](const double newTimestampMs) {
571
- if (auto strongThis = weakThis.lock()) {
572
- strongThis->cssLoopCallback(newTimestampMs);
573
- }
574
- });
575
- } else {
576
- cssLoopRunning_ = false;
577
- }
578
- }
579
-
580
- void ReanimatedModuleProxy::maybeRunCSSLoop() {
581
- if (cssLoopRunning_) {
582
- return;
583
- }
584
-
585
- cssLoopRunning_ = true;
586
-
587
- workletsModuleProxy_->getUIScheduler()->scheduleOnUI([weakThis = weak_from_this()]() {
588
- auto strongThis = weakThis.lock();
589
- if (!strongThis) {
590
- return;
591
- }
592
- strongThis->requestRender_([weakThis](const double timestampMs) {
593
- if (auto strongThis = weakThis.lock()) {
594
- strongThis->cssLoopCallback(timestampMs);
595
- }
596
- });
597
- });
598
- }
599
-
600
- double ReanimatedModuleProxy::getCssTimestamp() {
601
- if (cssLoopRunning_) {
602
- return currentCssTimestamp_;
603
- }
604
- currentCssTimestamp_ = getAnimationTimestamp_();
605
- return currentCssTimestamp_;
606
- }
607
-
608
- void ReanimatedModuleProxy::performOperations(const bool isTriggeredByEvent) {
609
- ReanimatedSystraceSection s("ReanimatedModuleProxy::performOperations");
610
-
611
- if (!isTriggeredByEvent) {
612
- auto flushRequestsCopy = std::move(layoutAnimationFlushRequests_);
613
- for (const auto surfaceId : flushRequestsCopy) {
614
- uiManager_->getShadowTreeRegistry().visit(
615
- surfaceId, [](const ShadowTree &shadowTree) { shadowTree.notifyDelegatesOfUpdates(); });
616
- }
617
- }
618
-
619
- jsi::Runtime &rt = workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
620
-
621
- UpdatesBatch updatesBatch;
622
- {
623
- ReanimatedSystraceSection s2("ReanimatedModuleProxy::flushUpdates");
624
-
625
- auto lock = updatesRegistryManager_->lock();
626
-
627
- if (shouldUpdateCssAnimations_) {
628
- currentCssTimestamp_ = getAnimationTimestamp_();
629
- auto lock = cssTransitionsRegistry_->lock();
630
- // Update CSS transitions and flush updates
631
- cssTransitionsRegistry_->update(currentCssTimestamp_);
632
- cssTransitionsRegistry_->flushUpdates(updatesBatch);
633
- }
634
-
635
- {
636
- auto lock = animatedPropsRegistry_->lock();
637
- // Flush all animated props updates
638
- animatedPropsRegistry_->flushUpdates(updatesBatch);
639
- }
640
-
641
- if (shouldUpdateCssAnimations_) {
642
- auto lock = cssAnimationsRegistry_->lock();
643
- // Update CSS animations and flush updates
644
- cssAnimationsRegistry_->update(currentCssTimestamp_);
645
- cssAnimationsRegistry_->flushUpdates(updatesBatch);
646
- }
647
-
648
- shouldUpdateCssAnimations_ = false;
649
-
650
- #ifdef ANDROID
651
- if constexpr (
652
- StaticFeatureFlags::getFlag("ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS") &&
653
- !StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS")) {
654
- static const std::unordered_set<std::string> synchronousProps = {
655
- "opacity",
656
- "elevation",
657
- "zIndex",
658
- // "shadowOpacity", // not supported on Android
659
- // "shadowRadius", // not supported on Android
660
- "backgroundColor",
661
- // "color", // TODO: fix animating color of Animated.Text
662
- "tintColor",
663
- "borderRadius",
664
- "borderTopLeftRadius",
665
- "borderTopRightRadius",
666
- "borderTopStartRadius",
667
- "borderTopEndRadius",
668
- "borderBottomLeftRadius",
669
- "borderBottomRightRadius",
670
- "borderBottomStartRadius",
671
- "borderBottomEndRadius",
672
- "borderStartStartRadius",
673
- "borderStartEndRadius",
674
- "borderEndStartRadius",
675
- "borderEndEndRadius",
676
- "borderColor",
677
- "borderTopColor",
678
- "borderBottomColor",
679
- "borderLeftColor",
680
- "borderRightColor",
681
- "borderStartColor",
682
- "borderEndColor",
683
- "transform",
684
- };
685
-
686
- // NOTE: Keep in sync with NativeProxy.java
687
- static constexpr auto CMD_START_OF_VIEW = 1;
688
- static constexpr auto CMD_START_OF_TRANSFORM = 2;
689
- static constexpr auto CMD_END_OF_TRANSFORM = 3;
690
- static constexpr auto CMD_END_OF_VIEW = 4;
691
-
692
- static constexpr auto CMD_OPACITY = 10;
693
- static constexpr auto CMD_ELEVATION = 11;
694
- static constexpr auto CMD_Z_INDEX = 12;
695
- static constexpr auto CMD_SHADOW_OPACITY = 13;
696
- static constexpr auto CMD_SHADOW_RADIUS = 14;
697
- static constexpr auto CMD_BACKGROUND_COLOR = 15;
698
- static constexpr auto CMD_COLOR = 16;
699
- static constexpr auto CMD_TINT_COLOR = 17;
700
-
701
- static constexpr auto CMD_BORDER_RADIUS = 20;
702
- static constexpr auto CMD_BORDER_TOP_LEFT_RADIUS = 21;
703
- static constexpr auto CMD_BORDER_TOP_RIGHT_RADIUS = 22;
704
- static constexpr auto CMD_BORDER_TOP_START_RADIUS = 23;
705
- static constexpr auto CMD_BORDER_TOP_END_RADIUS = 24;
706
- static constexpr auto CMD_BORDER_BOTTOM_LEFT_RADIUS = 25;
707
- static constexpr auto CMD_BORDER_BOTTOM_RIGHT_RADIUS = 26;
708
- static constexpr auto CMD_BORDER_BOTTOM_START_RADIUS = 27;
709
- static constexpr auto CMD_BORDER_BOTTOM_END_RADIUS = 28;
710
- static constexpr auto CMD_BORDER_START_START_RADIUS = 29;
711
- static constexpr auto CMD_BORDER_START_END_RADIUS = 30;
712
- static constexpr auto CMD_BORDER_END_START_RADIUS = 31;
713
- static constexpr auto CMD_BORDER_END_END_RADIUS = 32;
714
-
715
- static constexpr auto CMD_BORDER_COLOR = 40;
716
- static constexpr auto CMD_BORDER_TOP_COLOR = 41;
717
- static constexpr auto CMD_BORDER_BOTTOM_COLOR = 42;
718
- static constexpr auto CMD_BORDER_LEFT_COLOR = 43;
719
- static constexpr auto CMD_BORDER_RIGHT_COLOR = 44;
720
- static constexpr auto CMD_BORDER_START_COLOR = 45;
721
- static constexpr auto CMD_BORDER_END_COLOR = 46;
722
-
723
- static constexpr auto CMD_TRANSFORM_TRANSLATE_X = 100;
724
- static constexpr auto CMD_TRANSFORM_TRANSLATE_Y = 101;
725
- static constexpr auto CMD_TRANSFORM_SCALE = 102;
726
- static constexpr auto CMD_TRANSFORM_SCALE_X = 103;
727
- static constexpr auto CMD_TRANSFORM_SCALE_Y = 104;
728
- static constexpr auto CMD_TRANSFORM_ROTATE = 105;
729
- static constexpr auto CMD_TRANSFORM_ROTATE_X = 106;
730
- static constexpr auto CMD_TRANSFORM_ROTATE_Y = 107;
731
- static constexpr auto CMD_TRANSFORM_ROTATE_Z = 108;
732
- static constexpr auto CMD_TRANSFORM_SKEW_X = 109;
733
- static constexpr auto CMD_TRANSFORM_SKEW_Y = 110;
734
- static constexpr auto CMD_TRANSFORM_MATRIX = 111;
735
- static constexpr auto CMD_TRANSFORM_PERSPECTIVE = 112;
736
-
737
- static constexpr auto CMD_UNIT_DEG = 200;
738
- static constexpr auto CMD_UNIT_RAD = 201;
739
- static constexpr auto CMD_UNIT_PX = 202;
740
- static constexpr auto CMD_UNIT_PERCENT = 203;
741
-
742
- const auto propNameToCommand = [](const std::string &name) {
743
- if (name == "opacity")
744
- return CMD_OPACITY;
745
-
746
- if (name == "elevation")
747
- return CMD_ELEVATION;
748
-
749
- if (name == "zIndex")
750
- return CMD_Z_INDEX;
751
-
752
- if (name == "shadowOpacity")
753
- return CMD_SHADOW_OPACITY;
754
-
755
- if (name == "shadowRadius")
756
- return CMD_SHADOW_RADIUS;
757
-
758
- if (name == "backgroundColor")
759
- return CMD_BACKGROUND_COLOR;
760
-
761
- if (name == "color")
762
- return CMD_COLOR;
763
-
764
- if (name == "tintColor")
765
- return CMD_TINT_COLOR;
766
-
767
- if (name == "borderRadius")
768
- return CMD_BORDER_RADIUS;
769
-
770
- if (name == "borderTopLeftRadius")
771
- return CMD_BORDER_TOP_LEFT_RADIUS;
772
-
773
- if (name == "borderTopRightRadius")
774
- return CMD_BORDER_TOP_RIGHT_RADIUS;
775
-
776
- if (name == "borderTopStartRadius")
777
- return CMD_BORDER_TOP_START_RADIUS;
778
-
779
- if (name == "borderTopEndRadius")
780
- return CMD_BORDER_TOP_END_RADIUS;
781
-
782
- if (name == "borderBottomLeftRadius")
783
- return CMD_BORDER_BOTTOM_LEFT_RADIUS;
784
-
785
- if (name == "borderBottomRightRadius")
786
- return CMD_BORDER_BOTTOM_RIGHT_RADIUS;
787
-
788
- if (name == "borderBottomStartRadius")
789
- return CMD_BORDER_BOTTOM_START_RADIUS;
790
-
791
- if (name == "borderBottomEndRadius")
792
- return CMD_BORDER_BOTTOM_END_RADIUS;
793
-
794
- if (name == "borderStartStartRadius")
795
- return CMD_BORDER_START_START_RADIUS;
796
-
797
- if (name == "borderStartEndRadius")
798
- return CMD_BORDER_START_END_RADIUS;
799
-
800
- if (name == "borderEndStartRadius")
801
- return CMD_BORDER_END_START_RADIUS;
802
-
803
- if (name == "borderEndEndRadius")
804
- return CMD_BORDER_END_END_RADIUS;
805
-
806
- if (name == "borderColor")
807
- return CMD_BORDER_COLOR;
808
-
809
- if (name == "borderTopColor")
810
- return CMD_BORDER_TOP_COLOR;
811
-
812
- if (name == "borderBottomColor")
813
- return CMD_BORDER_BOTTOM_COLOR;
814
-
815
- if (name == "borderLeftColor")
816
- return CMD_BORDER_LEFT_COLOR;
817
-
818
- if (name == "borderRightColor")
819
- return CMD_BORDER_RIGHT_COLOR;
820
-
821
- if (name == "borderStartColor")
822
- return CMD_BORDER_START_COLOR;
823
-
824
- if (name == "borderEndColor")
825
- return CMD_BORDER_END_COLOR;
826
-
827
- if (name == "transform")
828
- return CMD_START_OF_TRANSFORM; // TODO: use CMD_TRANSFORM?
829
-
830
- throw std::runtime_error("[Reanimated] Unsupported style: " + name);
831
- };
832
-
833
- const auto transformNameToCommand = [](const std::string &name) {
834
- if (name == "translateX")
835
- return CMD_TRANSFORM_TRANSLATE_X;
836
-
837
- if (name == "translateY")
838
- return CMD_TRANSFORM_TRANSLATE_Y;
839
-
840
- if (name == "scale")
841
- return CMD_TRANSFORM_SCALE;
842
-
843
- if (name == "scaleX")
844
- return CMD_TRANSFORM_SCALE_X;
845
-
846
- if (name == "scaleY")
847
- return CMD_TRANSFORM_SCALE_Y;
848
-
849
- if (name == "rotate")
850
- return CMD_TRANSFORM_ROTATE;
851
-
852
- if (name == "rotateX")
853
- return CMD_TRANSFORM_ROTATE_X;
854
-
855
- if (name == "rotateY")
856
- return CMD_TRANSFORM_ROTATE_Y;
857
-
858
- if (name == "rotateZ")
859
- return CMD_TRANSFORM_ROTATE_Z;
860
-
861
- if (name == "skewX")
862
- return CMD_TRANSFORM_SKEW_X;
863
-
864
- if (name == "skewY")
865
- return CMD_TRANSFORM_SKEW_Y;
866
-
867
- if (name == "matrix")
868
- return CMD_TRANSFORM_MATRIX;
869
-
870
- if (name == "perspective")
871
- return CMD_TRANSFORM_PERSPECTIVE;
872
-
873
- throw std::runtime_error("[Reanimated] Unsupported transform: " + name);
874
- };
875
-
876
- UpdatesBatch synchronousUpdatesBatch, shadowTreeUpdatesBatch;
877
-
878
- for (const auto &[shadowNode, props] : updatesBatch) {
879
- bool hasOnlySynchronousProps = true;
880
- for (const auto &[key, value] : props.items()) {
881
- const auto keyStr = key.asString();
882
- if (!synchronousProps.contains(keyStr) ||
883
- ((keyStr == "color" || keyStr.find("Color") != std::string::npos) && !value.isInt())) {
884
- hasOnlySynchronousProps = false;
885
- break;
886
- }
887
- }
888
- if (hasOnlySynchronousProps) {
889
- synchronousUpdatesBatch.emplace_back(shadowNode, props);
890
- } else {
891
- shadowTreeUpdatesBatch.emplace_back(shadowNode, props);
892
- }
893
- }
894
-
895
- if (!synchronousUpdatesBatch.empty()) {
896
- std::vector<int> intBuffer;
897
- std::vector<double> doubleBuffer;
898
- intBuffer.reserve(1024);
899
- doubleBuffer.reserve(1024);
900
-
901
- for (const auto &[shadowNode, props] : synchronousUpdatesBatch) {
902
- intBuffer.push_back(CMD_START_OF_VIEW);
903
- intBuffer.push_back(shadowNode->getTag());
904
- for (const auto &[key, value] : props.items()) {
905
- const auto command = propNameToCommand(key.getString());
906
- switch (command) {
907
- case CMD_OPACITY:
908
- case CMD_ELEVATION:
909
- case CMD_Z_INDEX:
910
- case CMD_SHADOW_OPACITY:
911
- case CMD_SHADOW_RADIUS:
912
- intBuffer.push_back(command);
913
- doubleBuffer.push_back(value.asDouble());
914
- break;
915
-
916
- case CMD_BACKGROUND_COLOR:
917
- case CMD_COLOR:
918
- case CMD_TINT_COLOR:
919
- case CMD_BORDER_COLOR:
920
- case CMD_BORDER_TOP_COLOR:
921
- case CMD_BORDER_BOTTOM_COLOR:
922
- case CMD_BORDER_LEFT_COLOR:
923
- case CMD_BORDER_RIGHT_COLOR:
924
- case CMD_BORDER_START_COLOR:
925
- case CMD_BORDER_END_COLOR:
926
- intBuffer.push_back(command);
927
- intBuffer.push_back(value.asInt());
928
- break;
929
-
930
- case CMD_BORDER_RADIUS:
931
- case CMD_BORDER_TOP_LEFT_RADIUS:
932
- case CMD_BORDER_TOP_RIGHT_RADIUS:
933
- case CMD_BORDER_TOP_START_RADIUS:
934
- case CMD_BORDER_TOP_END_RADIUS:
935
- case CMD_BORDER_BOTTOM_LEFT_RADIUS:
936
- case CMD_BORDER_BOTTOM_RIGHT_RADIUS:
937
- case CMD_BORDER_BOTTOM_START_RADIUS:
938
- case CMD_BORDER_BOTTOM_END_RADIUS:
939
- case CMD_BORDER_START_START_RADIUS:
940
- case CMD_BORDER_START_END_RADIUS:
941
- case CMD_BORDER_END_START_RADIUS:
942
- case CMD_BORDER_END_END_RADIUS:
943
- intBuffer.push_back(command);
944
- if (value.isDouble()) {
945
- intBuffer.push_back(CMD_UNIT_PX);
946
- doubleBuffer.push_back(value.getDouble());
947
- } else if (value.isString()) {
948
- const auto &valueStr = value.getString();
949
- if (!valueStr.ends_with("%")) {
950
- throw std::runtime_error("[Reanimated] Border radius string must be a percentage");
951
- }
952
- intBuffer.push_back(CMD_UNIT_PERCENT);
953
- doubleBuffer.push_back(std::stof(valueStr.substr(0, -1)));
954
- } else {
955
- throw std::runtime_error("[Reanimated] Border radius value must be either a number or a string");
956
- }
957
- break;
958
-
959
- case CMD_START_OF_TRANSFORM:
960
- intBuffer.push_back(command);
961
- react_native_assert(value.isArray() && "[Reanimated] Transform value must be an array");
962
- for (const auto &item : value) {
963
- react_native_assert(item.isObject() && "[Reanimated] Transform array item must be an object");
964
- react_native_assert(
965
- item.size() == 1 && "[Reanimated] Transform array item must have exactly one key-value pair");
966
- const auto transformCommand = transformNameToCommand(item.keys().begin()->getString());
967
- const auto &transformValue = *item.values().begin();
968
- switch (transformCommand) {
969
- case CMD_TRANSFORM_SCALE:
970
- case CMD_TRANSFORM_SCALE_X:
971
- case CMD_TRANSFORM_SCALE_Y:
972
- case CMD_TRANSFORM_PERSPECTIVE: {
973
- intBuffer.push_back(transformCommand);
974
- doubleBuffer.push_back(transformValue.asDouble());
975
- break;
976
- }
977
-
978
- case CMD_TRANSFORM_TRANSLATE_X:
979
- case CMD_TRANSFORM_TRANSLATE_Y: {
980
- intBuffer.push_back(transformCommand);
981
- if (transformValue.isDouble()) {
982
- intBuffer.push_back(CMD_UNIT_PX);
983
- doubleBuffer.push_back(transformValue.getDouble());
984
- } else if (transformValue.isString()) {
985
- const auto &transformValueStr = transformValue.getString();
986
- if (!transformValueStr.ends_with("%")) {
987
- throw std::runtime_error("[Reanimated] String translate must be a percentage");
988
- }
989
- intBuffer.push_back(CMD_UNIT_PERCENT);
990
- doubleBuffer.push_back(std::stof(transformValueStr.substr(0, -1)));
991
- } else {
992
- throw std::runtime_error("[Reanimated] Translate value must be either a number or a string");
993
- }
994
- break;
995
- }
996
-
997
- case CMD_TRANSFORM_ROTATE:
998
- case CMD_TRANSFORM_ROTATE_X:
999
- case CMD_TRANSFORM_ROTATE_Y:
1000
- case CMD_TRANSFORM_ROTATE_Z:
1001
- case CMD_TRANSFORM_SKEW_X:
1002
- case CMD_TRANSFORM_SKEW_Y: {
1003
- const auto &transformValueStr = transformValue.getString();
1004
- intBuffer.push_back(transformCommand);
1005
- if (transformValueStr.ends_with("deg")) {
1006
- intBuffer.push_back(CMD_UNIT_DEG);
1007
- } else if (transformValueStr.ends_with("rad")) {
1008
- intBuffer.push_back(CMD_UNIT_RAD);
1009
- } else {
1010
- throw std::runtime_error("[Reanimated] Unsupported rotation unit: " + transformValueStr);
1011
- }
1012
- doubleBuffer.push_back(std::stof(transformValueStr.substr(0, -3)));
1013
- break;
1014
- }
1015
-
1016
- case CMD_TRANSFORM_MATRIX: {
1017
- intBuffer.push_back(transformCommand);
1018
- react_native_assert(transformValue.isArray() && "[Reanimated] Matrix must be an array");
1019
- int size = transformValue.size();
1020
- intBuffer.push_back(size);
1021
- for (int i = 0; i < size; i++) {
1022
- doubleBuffer.push_back(transformValue[i].asDouble());
1023
- }
1024
- break;
1025
- }
1026
- }
1027
- }
1028
- intBuffer.push_back(CMD_END_OF_TRANSFORM);
1029
- break;
1030
- }
1031
- }
1032
- intBuffer.push_back(CMD_END_OF_VIEW);
1033
- }
1034
- synchronouslyUpdateUIPropsFunction_(intBuffer, doubleBuffer);
1035
- }
1036
-
1037
- updatesBatch = std::move(shadowTreeUpdatesBatch);
1038
- }
1039
- #endif // ANDROID
1040
-
1041
- #if __APPLE__
1042
- if constexpr (
1043
- StaticFeatureFlags::getFlag("IOS_SYNCHRONOUSLY_UPDATE_UI_PROPS") &&
1044
- !StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS")) {
1045
- static const std::unordered_set<std::string> synchronousProps = {
1046
- "opacity",
1047
- "elevation",
1048
- "zIndex",
1049
- "shadowOpacity",
1050
- "shadowRadius",
1051
- "backgroundColor",
1052
- // "color", // TODO: fix animating color of Animated.Text
1053
- "tintColor",
1054
- "borderRadius",
1055
- "borderTopLeftRadius",
1056
- "borderTopRightRadius",
1057
- "borderTopStartRadius",
1058
- "borderTopEndRadius",
1059
- "borderBottomLeftRadius",
1060
- "borderBottomRightRadius",
1061
- "borderBottomStartRadius",
1062
- "borderBottomEndRadius",
1063
- "borderStartStartRadius",
1064
- "borderStartEndRadius",
1065
- "borderEndStartRadius",
1066
- "borderEndEndRadius",
1067
- "borderColor",
1068
- "borderTopColor",
1069
- "borderBottomColor",
1070
- "borderLeftColor",
1071
- "borderRightColor",
1072
- "borderStartColor",
1073
- "borderEndColor",
1074
- "transform",
1075
- };
1076
-
1077
- UpdatesBatch synchronousUpdatesBatch, shadowTreeUpdatesBatch;
1078
-
1079
- for (const auto &[shadowNode, props] : updatesBatch) {
1080
- bool hasOnlySynchronousProps = true;
1081
- for (const auto &key : props.keys()) {
1082
- const auto keyStr = key.asString();
1083
- if (!synchronousProps.contains(keyStr)) {
1084
- hasOnlySynchronousProps = false;
1085
- break;
1086
- }
1087
- }
1088
- if (hasOnlySynchronousProps) {
1089
- synchronousUpdatesBatch.emplace_back(shadowNode, props);
1090
- } else {
1091
- shadowTreeUpdatesBatch.emplace_back(shadowNode, props);
1092
- }
1093
- }
1094
-
1095
- for (const auto &[shadowNode, props] : synchronousUpdatesBatch) {
1096
- synchronouslyUpdateUIPropsFunction_(shadowNode->getTag(), props);
1097
- }
1098
-
1099
- updatesBatch = std::move(shadowTreeUpdatesBatch);
1100
- }
1101
- #endif // __APPLE__
1102
-
1103
- if ((updatesBatch.size() > 0) && updatesRegistryManager_->shouldReanimatedSkipCommit()) {
1104
- updatesRegistryManager_->pleaseCommitAfterPause();
1105
- }
1106
- }
1107
-
1108
- if (updatesRegistryManager_->shouldReanimatedSkipCommit()) {
1109
- // It may happen that `performOperations` is called on the UI thread
1110
- // while React Native tries to commit a new tree on the JS thread.
1111
- // In this case, we should skip the commit here and let React Native do
1112
- // it. The commit will include the current values from the updates manager
1113
- // which will be applied in ReanimatedCommitHook.
1114
- return;
1115
- }
1116
-
1117
- commitUpdates(rt, updatesBatch);
1118
-
1119
- // Clear the entire cache after the commit
1120
- // (we don't know if the view is updated from outside of Reanimated
1121
- // so we have to clear the entire cache)
1122
- viewStylesRepository_->clearNodesCache();
1123
- }
1124
-
1125
- void ReanimatedModuleProxy::requestFlushRegistry() {
1126
- requestRender_([weakThis = weak_from_this()](const double timestamp) {
1127
- if (auto strongThis = weakThis.lock()) {
1128
- strongThis->shouldFlushRegistry_ = true;
1129
- }
1130
- });
1131
- }
1132
-
1133
- void ReanimatedModuleProxy::commitUpdates(jsi::Runtime &rt, const UpdatesBatch &updatesBatch) {
1134
- ReanimatedSystraceSection s("ReanimatedModuleProxy::commitUpdates");
1135
- react_native_assert(uiManager_ != nullptr);
1136
- const auto &shadowTreeRegistry = uiManager_->getShadowTreeRegistry();
1137
-
1138
- std::unordered_map<SurfaceId, PropsMap> propsMapBySurface;
1139
-
1140
- #ifdef ANDROID
1141
- updatesRegistryManager_->collectPropsToRevertBySurface(propsMapBySurface);
1142
- #endif
1143
-
1144
- if (shouldFlushRegistry_) {
1145
- shouldFlushRegistry_ = false;
1146
- const auto propsMap = updatesRegistryManager_->collectProps();
1147
- for (auto const &[family, props] : propsMap) {
1148
- const auto surfaceId = family->getSurfaceId();
1149
- auto &propsVector = propsMapBySurface[surfaceId][family];
1150
- for (const auto &prop : props) {
1151
- propsVector.emplace_back(prop);
1152
- }
1153
- }
1154
- } else {
1155
- for (auto const &[shadowNode, props] : updatesBatch) {
1156
- SurfaceId surfaceId = shadowNode->getSurfaceId();
1157
- auto family = &shadowNode->getFamily();
1158
- react_native_assert(family->getSurfaceId() == surfaceId);
1159
- propsMapBySurface[surfaceId][family].emplace_back(props);
1160
- }
1161
- }
1162
-
1163
- for (const auto &entry : propsMapBySurface) {
1164
- const SurfaceId surfaceId = entry.first;
1165
- const PropsMap &propsMap = entry.second;
1166
- shadowTreeRegistry.visit(surfaceId, [&](ShadowTree const &shadowTree) {
1167
- const auto status = shadowTree.commit(
1168
- [&](RootShadowNode const &oldRootShadowNode) -> RootShadowNode::Unshared {
1169
- if (updatesRegistryManager_->shouldReanimatedSkipCommit()) {
1170
- return nullptr;
1171
- }
1172
-
1173
- auto rootNode = cloneShadowTreeWithNewProps(oldRootShadowNode, propsMap);
1174
-
1175
- // Mark the commit as Reanimated commit so that we can distinguish
1176
- // it in ReanimatedCommitHook.
1177
-
1178
- auto reaShadowNode = std::reinterpret_pointer_cast<ReanimatedCommitShadowNode>(rootNode);
1179
- reaShadowNode->setReanimatedCommitTrait();
1180
-
1181
- return rootNode;
1182
- },
1183
- {/* .enableStateReconciliation = */
1184
- false,
1185
- /* .mountSynchronously = */ true});
1186
-
1187
- #ifdef ANDROID
1188
- if (status == ShadowTree::CommitStatus::Succeeded) {
1189
- updatesRegistryManager_->clearPropsToRevert(surfaceId);
1190
- }
1191
- #else
1192
- (void)status;
1193
- #endif
1194
- });
1195
- }
1196
- }
1197
-
1198
- void ReanimatedModuleProxy::dispatchCommand(
1199
- jsi::Runtime &rt,
1200
- const jsi::Value &shadowNodeValue,
1201
- const jsi::Value &commandNameValue,
1202
- const jsi::Value &argsValue) {
1203
- const auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
1204
- std::string commandName = stringFromValue(rt, commandNameValue);
1205
- folly::dynamic args = commandArgsFromValue(rt, argsValue);
1206
- const auto &scheduler = static_cast<Scheduler *>(uiManager_->getDelegate());
1207
-
1208
- if (!scheduler) {
1209
- return;
1210
- }
1211
-
1212
- const auto &schedulerDelegate = scheduler->getDelegate();
1213
-
1214
- if (schedulerDelegate) {
1215
- const auto shadowView = ShadowView(*shadowNode);
1216
- schedulerDelegate->schedulerDidDispatchCommand(shadowView, commandName, args);
1217
- }
1218
- }
1219
-
1220
- jsi::String
1221
- ReanimatedModuleProxy::obtainProp(jsi::Runtime &rt, const jsi::Value &shadowNodeWrapper, const jsi::Value &propName) {
1222
- jsi::Runtime &uiRuntime = workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
1223
- const auto propNameStr = propName.asString(rt).utf8(rt);
1224
- const auto shadowNode = shadowNodeFromValue(rt, shadowNodeWrapper);
1225
- const auto resultStr = obtainPropFromShadowNode(uiRuntime, propNameStr, shadowNode);
1226
- return jsi::String::createFromUtf8(rt, resultStr);
1227
- }
1228
-
1229
- jsi::Value ReanimatedModuleProxy::measure(jsi::Runtime &rt, const jsi::Value &shadowNodeValue) {
1230
- // based on implementation from UIManagerBinding.cpp
1231
-
1232
- auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
1233
- auto layoutMetrics = uiManager_->getRelativeLayoutMetrics(*shadowNode, nullptr, {/* .includeTransform = */ true});
1234
-
1235
- if (layoutMetrics == EmptyLayoutMetrics) {
1236
- // Originally, in this case React Native returns `{0, 0, 0, 0, 0, 0}`,
1237
- // most likely due to the type of measure callback function which accepts
1238
- // just an array of numbers (not null). In Reanimated, `measure` returns
1239
- // `MeasuredDimensions | null`.
1240
- return jsi::Value::null();
1241
- }
1242
- auto newestCloneOfShadowNode = uiManager_->getNewestCloneOfShadowNode(*shadowNode);
1243
-
1244
- auto layoutableShadowNode = dynamic_cast<LayoutableShadowNode const *>(newestCloneOfShadowNode.get());
1245
- facebook::react::Point originRelativeToParent = layoutableShadowNode != nullptr
1246
- ? layoutableShadowNode->getLayoutMetrics().frame.origin
1247
- : facebook::react::Point();
1248
-
1249
- auto frame = layoutMetrics.frame;
1250
-
1251
- jsi::Object result(rt);
1252
- result.setProperty(rt, "x", jsi::Value(static_cast<double>(originRelativeToParent.x)));
1253
- result.setProperty(rt, "y", jsi::Value(static_cast<double>(originRelativeToParent.y)));
1254
- result.setProperty(rt, "width", jsi::Value(static_cast<double>(frame.size.width)));
1255
- result.setProperty(rt, "height", jsi::Value(static_cast<double>(frame.size.height)));
1256
- result.setProperty(rt, "pageX", jsi::Value(static_cast<double>(frame.origin.x)));
1257
- result.setProperty(rt, "pageY", jsi::Value(static_cast<double>(frame.origin.y)));
1258
- return result;
1259
- }
1260
-
1261
- void ReanimatedModuleProxy::initializeFabric(const std::shared_ptr<UIManager> &uiManager) {
1262
- uiManager_ = uiManager;
1263
- viewStylesRepository_->setUIManager(uiManager_);
1264
-
1265
- initializeLayoutAnimationsProxy();
1266
-
1267
- const std::function<void()> request = [weakThis = weak_from_this()]() {
1268
- auto strongThis = weakThis.lock();
1269
- if (!strongThis) {
1270
- return;
1271
- }
1272
-
1273
- strongThis->requestFlushRegistry();
1274
- };
1275
- mountHook_ = std::make_shared<ReanimatedMountHook>(uiManager_, updatesRegistryManager_, request);
1276
- commitHook_ = std::make_shared<ReanimatedCommitHook>(uiManager_, updatesRegistryManager_, layoutAnimationsProxy_);
1277
- }
1278
-
1279
- void ReanimatedModuleProxy::initializeLayoutAnimationsProxy() {
1280
- auto scheduler = reinterpret_cast<Scheduler *>(uiManager_->getDelegate());
1281
- auto componentDescriptorRegistry =
1282
- scheduler->getContextContainer()
1283
- ->at<std::weak_ptr<const ComponentDescriptorRegistry>>("ComponentDescriptorRegistry_DO_NOT_USE_PRETTY_PLEASE")
1284
- .lock();
1285
-
1286
- if (componentDescriptorRegistry) {
1287
- if constexpr (StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS")) {
1288
- auto layoutAnimationsProxyExperimental = std::make_shared<LayoutAnimationsProxy_Experimental>(
1289
- layoutAnimationsManager_,
1290
- componentDescriptorRegistry,
1291
- scheduler->getContextContainer(),
1292
- workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime(),
1293
- workletsModuleProxy_->getUIScheduler()
1294
- #ifdef ANDROID
1295
- ,
1296
- filterUnmountedTagsFunction_,
1297
- uiManager_,
1298
- jsInvoker_
1299
- #endif
1300
- );
1301
- #ifdef __APPLE__
1302
- layoutAnimationsProxyExperimental->setForceScreenSnapshotFunction(forceScreenSnapshot_);
1303
- #endif
1304
- layoutAnimationsProxy_ = std::move(layoutAnimationsProxyExperimental);
1305
- } else {
1306
- auto layoutAnimationsProxyLegacy = std::make_shared<LayoutAnimationsProxy_Legacy>(
1307
- layoutAnimationsManager_,
1308
- componentDescriptorRegistry,
1309
- scheduler->getContextContainer(),
1310
- workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime(),
1311
- workletsModuleProxy_->getUIScheduler()
1312
- #ifdef ANDROID
1313
- ,
1314
- filterUnmountedTagsFunction_,
1315
- uiManager_,
1316
- jsInvoker_
1317
- #endif
1318
- );
1319
- // TODO (future): support in experimental
1320
- uiManager_->setAnimationDelegate(layoutAnimationsProxyLegacy.get());
1321
- layoutAnimationsProxy_ = std::move(layoutAnimationsProxyLegacy);
1322
- }
1323
- }
1324
- }
1325
-
1326
- #ifdef IS_REANIMATED_EXAMPLE_APP
1327
-
1328
- std::string format(bool b) {
1329
- return b ? "✅" : "❌";
1330
- }
1331
-
1332
- std::function<std::string()> ReanimatedModuleProxy::createRegistriesLeakCheck() {
1333
- return [weakThis = weak_from_this()]() {
1334
- auto strongThis = weakThis.lock();
1335
- if (!strongThis) {
1336
- return std::string("");
1337
- }
1338
-
1339
- std::string result = "";
1340
-
1341
- result += "AnimatedPropsRegistry: " + format(strongThis->animatedPropsRegistry_->isEmpty());
1342
- result += "\nCSSAnimationsRegistry: " + format(strongThis->cssAnimationsRegistry_->isEmpty());
1343
- result += "\nCSSTransitionsRegistry: " + format(strongThis->cssTransitionsRegistry_->isEmpty());
1344
- result += "\nStaticPropsRegistry: " + format(strongThis->staticPropsRegistry_->isEmpty()) + "\n";
1345
-
1346
- return result;
1347
- };
1348
- }
1349
-
1350
- #endif // IS_REANIMATED_EXAMPLE_APP
1351
-
1352
- jsi::Value ReanimatedModuleProxy::subscribeForKeyboardEvents(
1353
- jsi::Runtime &rt,
1354
- const jsi::Value &handlerWorklet,
1355
- const jsi::Value &isStatusBarTranslucent,
1356
- const jsi::Value &isNavigationBarTranslucent) {
1357
- auto serializableHandler = extractSerializableOrThrow<SerializableWorklet>(
1358
- rt, handlerWorklet, "[Reanimated] Keyboard event handler must be a worklet.");
1359
- return subscribeForKeyboardEventsFunction_(
1360
- [=, weakThis = weak_from_this()](int keyboardState, int height) {
1361
- auto strongThis = weakThis.lock();
1362
- if (!strongThis) {
1363
- return;
1364
- }
1365
- strongThis->workletsModuleProxy_->getUIWorkletRuntime()->runSync(
1366
- serializableHandler, jsi::Value(keyboardState), jsi::Value(height));
1367
- },
1368
- isStatusBarTranslucent.getBool(),
1369
- isNavigationBarTranslucent.getBool());
1370
- }
1371
-
1372
- void ReanimatedModuleProxy::unsubscribeFromKeyboardEvents(jsi::Runtime &, const jsi::Value &listenerId) {
1373
- unsubscribeFromKeyboardEventsFunction_(listenerId.asNumber());
1374
- }
1375
-
1376
- } // namespace reanimated
1
+ #include <jsi/jsi.h>
2
+ #include <reanimated/NativeModules/PropValueProcessor.h>
3
+ #include <reanimated/NativeModules/ReanimatedModuleProxy.h>
4
+ #include <reanimated/RuntimeDecorators/UIRuntimeDecorator.h>
5
+ #include <reanimated/Tools/FeatureFlags.h>
6
+ #include <reanimated/Tools/ReanimatedSystraceSection.h>
7
+
8
+ #include <worklets/Registries/EventHandlerRegistry.h>
9
+ #include <worklets/SharedItems/Serializable.h>
10
+ #include <worklets/Tools/WorkletEventHandler.h>
11
+
12
+ #ifdef __ANDROID__
13
+ #include <fbjni/fbjni.h>
14
+ #endif // __ANDROID__
15
+
16
+ #include <react/renderer/scheduler/Scheduler.h>
17
+ #include <react/renderer/uimanager/UIManagerBinding.h>
18
+ #include <reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h>
19
+ #include <reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.h>
20
+
21
+ #include <functional>
22
+ #include <iomanip>
23
+ #include <memory>
24
+ #include <sstream>
25
+ #include <string>
26
+ #include <unordered_map>
27
+ #include <unordered_set>
28
+ #include <utility>
29
+ #include <vector>
30
+
31
+ namespace reanimated {
32
+
33
+ #if REACT_NATIVE_MINOR_VERSION >= 81
34
+ static inline std::shared_ptr<const ShadowNode> shadowNodeFromValue(
35
+ jsi::Runtime &rt,
36
+ const jsi::Value &shadowNodeWrapper) {
37
+ return Bridging<std::shared_ptr<const ShadowNode>>::fromJs(rt, shadowNodeWrapper);
38
+ }
39
+ #endif
40
+
41
+ ReanimatedModuleProxy::ReanimatedModuleProxy(
42
+ const std::shared_ptr<WorkletsModuleProxy> &workletsModuleProxy,
43
+ jsi::Runtime &rnRuntime,
44
+ const std::shared_ptr<CallInvoker> &jsCallInvoker,
45
+ const PlatformDepMethodsHolder &platformDepMethodsHolder,
46
+ const bool isReducedMotion)
47
+ : ReanimatedModuleProxySpec(jsCallInvoker),
48
+ isReducedMotion_(isReducedMotion),
49
+ workletsModuleProxy_(workletsModuleProxy),
50
+ eventHandlerRegistry_(std::make_unique<EventHandlerRegistry>()),
51
+ requestRender_(platformDepMethodsHolder.requestRender),
52
+ animatedSensorModule_(platformDepMethodsHolder),
53
+ jsLogger_(std::make_shared<JSLogger>(workletsModuleProxy->getJSScheduler())),
54
+ layoutAnimationsManager_(std::make_shared<LayoutAnimationsManager>(jsLogger_)),
55
+ getAnimationTimestamp_(platformDepMethodsHolder.getAnimationTimestamp),
56
+ #ifdef __APPLE__
57
+ forceScreenSnapshot_(platformDepMethodsHolder.forceScreenSnapshotFunction),
58
+ #endif
59
+ animatedPropsRegistry_(std::make_shared<AnimatedPropsRegistry>()),
60
+ staticPropsRegistry_(std::make_shared<StaticPropsRegistry>()),
61
+ updatesRegistryManager_(std::make_shared<UpdatesRegistryManager>(staticPropsRegistry_)),
62
+ viewStylesRepository_(std::make_shared<ViewStylesRepository>(staticPropsRegistry_, animatedPropsRegistry_)),
63
+ cssAnimationKeyframesRegistry_(std::make_shared<CSSKeyframesRegistry>(viewStylesRepository_)),
64
+ cssAnimationsRegistry_(std::make_shared<CSSAnimationsRegistry>()),
65
+ cssTransitionsRegistry_(std::make_shared<CSSTransitionsRegistry>(staticPropsRegistry_, getAnimationTimestamp_)),
66
+ synchronouslyUpdateUIPropsFunction_(platformDepMethodsHolder.synchronouslyUpdateUIPropsFunction),
67
+ #ifdef ANDROID
68
+ filterUnmountedTagsFunction_(platformDepMethodsHolder.filterUnmountedTagsFunction),
69
+ #endif // ANDROID
70
+ subscribeForKeyboardEventsFunction_(platformDepMethodsHolder.subscribeForKeyboardEvents),
71
+ unsubscribeFromKeyboardEventsFunction_(platformDepMethodsHolder.unsubscribeFromKeyboardEvents) {
72
+ auto lock = updatesRegistryManager_->lock();
73
+ // Add registries in order of their priority (from the lowest to the
74
+ // highest)
75
+ // CSS transitions should be overriden by animated style animations;
76
+ // animated style animations should be overriden by CSS animations
77
+ updatesRegistryManager_->addRegistry(cssTransitionsRegistry_);
78
+ updatesRegistryManager_->addRegistry(animatedPropsRegistry_);
79
+ updatesRegistryManager_->addRegistry(cssAnimationsRegistry_);
80
+ }
81
+
82
+ void ReanimatedModuleProxy::init(const PlatformDepMethodsHolder &platformDepMethodsHolder) {
83
+ auto onRenderCallback = [weakThis = weak_from_this()](const double timestampMs) {
84
+ auto strongThis = weakThis.lock();
85
+ if (!strongThis) {
86
+ return;
87
+ }
88
+
89
+ strongThis->renderRequested_ = false;
90
+ strongThis->onRender(timestampMs);
91
+ };
92
+ onRenderCallback_ = std::move(onRenderCallback);
93
+
94
+ auto updateProps = [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &operations) {
95
+ auto strongThis = weakThis.lock();
96
+ if (!strongThis) {
97
+ return;
98
+ }
99
+
100
+ const auto timestamp = strongThis->getAnimationTimestamp_();
101
+ strongThis->animatedPropsRegistry_->update(rt, operations, timestamp);
102
+ };
103
+
104
+ auto measure = [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &shadowNodeValue) -> jsi::Value {
105
+ auto strongThis = weakThis.lock();
106
+ if (!strongThis) {
107
+ return jsi::Value::undefined();
108
+ }
109
+ return strongThis->measure(rt, shadowNodeValue);
110
+ };
111
+
112
+ auto dispatchCommand = [weakThis = weak_from_this()](
113
+ jsi::Runtime &rt,
114
+ const jsi::Value &shadowNodeValue,
115
+ const jsi::Value &commandNameValue,
116
+ const jsi::Value &argsValue) {
117
+ auto strongThis = weakThis.lock();
118
+ if (!strongThis) {
119
+ return;
120
+ }
121
+
122
+ strongThis->dispatchCommand(rt, shadowNodeValue, commandNameValue, argsValue);
123
+ };
124
+ ProgressLayoutAnimationFunction progressLayoutAnimation =
125
+ [weakThis = weak_from_this()](jsi::Runtime &rt, int tag, const jsi::Object &newStyle) {
126
+ auto strongThis = weakThis.lock();
127
+ if (!strongThis) {
128
+ return;
129
+ }
130
+ auto surfaceId = strongThis->layoutAnimationsProxy_->progressLayoutAnimation(tag, newStyle);
131
+ if (!surfaceId) {
132
+ return;
133
+ }
134
+ strongThis->layoutAnimationFlushRequests_.insert(*surfaceId);
135
+ };
136
+
137
+ auto requestLayoutAnimationRender = [weakThis = weak_from_this()](double) {
138
+ auto strongThis = weakThis.lock();
139
+ if (!strongThis) {
140
+ return;
141
+ }
142
+ strongThis->layoutAnimationRenderRequested_ = false;
143
+ };
144
+
145
+ EndLayoutAnimationFunction endLayoutAnimation = [weakThis = weak_from_this(), requestLayoutAnimationRender](
146
+ int tag, bool shouldRemove) {
147
+ auto strongThis = weakThis.lock();
148
+ if (!strongThis) {
149
+ return;
150
+ }
151
+
152
+ auto surfaceId = strongThis->layoutAnimationsProxy_->endLayoutAnimation(tag, shouldRemove);
153
+
154
+ if (!strongThis->layoutAnimationRenderRequested_) {
155
+ strongThis->layoutAnimationRenderRequested_ = true;
156
+ // if an animation has duration 0, performOperations would not get
157
+ // called for it so we call requestRender to have it called in the
158
+ // next frame
159
+ strongThis->requestRender_(requestLayoutAnimationRender);
160
+ }
161
+
162
+ if (!surfaceId) {
163
+ return;
164
+ }
165
+ strongThis->layoutAnimationFlushRequests_.insert(*surfaceId);
166
+ };
167
+
168
+ auto obtainProp = [weakThis = weak_from_this()](
169
+ jsi::Runtime &rt, const jsi::Value &shadowNodeWrapper, const jsi::Value &propName) {
170
+ auto strongThis = weakThis.lock();
171
+ if (!strongThis) {
172
+ return jsi::String::createFromUtf8(rt, "");
173
+ }
174
+
175
+ return strongThis->obtainProp(rt, shadowNodeWrapper, propName);
176
+ };
177
+
178
+ jsi::Runtime &uiRuntime = workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
179
+ UIRuntimeDecorator::decorate(
180
+ uiRuntime,
181
+ obtainProp,
182
+ updateProps,
183
+ measure,
184
+ dispatchCommand,
185
+ platformDepMethodsHolder.getAnimationTimestamp,
186
+ platformDepMethodsHolder.setGestureStateFunction,
187
+ progressLayoutAnimation,
188
+ endLayoutAnimation,
189
+ platformDepMethodsHolder.maybeFlushUIUpdatesQueueFunction);
190
+ }
191
+
192
+ ReanimatedModuleProxy::~ReanimatedModuleProxy() {
193
+ invalidate();
194
+ }
195
+
196
+ void ReanimatedModuleProxy::invalidate() {
197
+ // event handler registry and frame callbacks store some JSI values from UI
198
+ // runtime, so they have to go away before we tear down the runtime
199
+ eventHandlerRegistry_.reset();
200
+ }
201
+
202
+ jsi::Value ReanimatedModuleProxy::registerEventHandler(
203
+ jsi::Runtime &rt,
204
+ const jsi::Value &worklet,
205
+ const jsi::Value &eventName,
206
+ const jsi::Value &emitterReactTag) {
207
+ static uint64_t NEXT_EVENT_HANDLER_ID = 1;
208
+
209
+ uint64_t newRegistrationId = NEXT_EVENT_HANDLER_ID++;
210
+ auto eventNameStr = eventName.asString(rt).utf8(rt);
211
+ auto handlerSerializable = extractSerializableOrThrow<SerializableWorklet>(
212
+ rt, worklet, "[Reanimated] Event handler must be a serializable worklet.");
213
+ int emitterReactTagInt = emitterReactTag.asNumber();
214
+
215
+ workletsModuleProxy_->getUIScheduler()->scheduleOnUI([=, weakThis = weak_from_this()]() {
216
+ auto strongThis = weakThis.lock();
217
+ if (!strongThis) {
218
+ return;
219
+ }
220
+ auto handler =
221
+ std::make_shared<WorkletEventHandler>(newRegistrationId, eventNameStr, emitterReactTagInt, handlerSerializable);
222
+ strongThis->eventHandlerRegistry_->registerEventHandler(handler);
223
+ });
224
+
225
+ return jsi::Value(static_cast<double>(newRegistrationId));
226
+ }
227
+
228
+ void ReanimatedModuleProxy::unregisterEventHandler(jsi::Runtime &, const jsi::Value &registrationId) {
229
+ uint64_t id = registrationId.asNumber();
230
+ workletsModuleProxy_->getUIScheduler()->scheduleOnUI([=, weakThis = weak_from_this()]() {
231
+ auto strongThis = weakThis.lock();
232
+ if (!strongThis) {
233
+ return;
234
+ }
235
+ strongThis->eventHandlerRegistry_->unregisterEventHandler(id);
236
+ });
237
+ }
238
+
239
+ std::string ReanimatedModuleProxy::obtainPropFromShadowNode(
240
+ jsi::Runtime &rt,
241
+ const std::string &propName,
242
+ const std::shared_ptr<const ShadowNode> &shadowNode) {
243
+ auto newestCloneOfShadowNode = uiManager_->getNewestCloneOfShadowNode(*shadowNode);
244
+
245
+ return PropValueProcessor::processPropValue(propName, newestCloneOfShadowNode, rt);
246
+ }
247
+
248
+ jsi::Value ReanimatedModuleProxy::getViewProp(
249
+ jsi::Runtime &rnRuntime,
250
+ const jsi::Value &shadowNodeWrapper,
251
+ const jsi::Value &propName,
252
+ const jsi::Value &callback) {
253
+ const auto propNameStr = propName.asString(rnRuntime).utf8(rnRuntime);
254
+ const auto funPtr = std::make_shared<jsi::Function>(callback.getObject(rnRuntime).asFunction(rnRuntime));
255
+ const auto shadowNode = shadowNodeFromValue(rnRuntime, shadowNodeWrapper);
256
+ workletsModuleProxy_->getUIScheduler()->scheduleOnUI([=, weakThis = weak_from_this()]() {
257
+ auto strongThis = weakThis.lock();
258
+ if (!strongThis) {
259
+ return;
260
+ }
261
+ jsi::Runtime &uiRuntime = strongThis->workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
262
+ const auto resultStr = strongThis->obtainPropFromShadowNode(uiRuntime, propNameStr, shadowNode);
263
+
264
+ strongThis->workletsModuleProxy_->getJSScheduler()->scheduleOnJS([=](jsi::Runtime &rnRuntime) {
265
+ const auto resultValue = jsi::String::createFromUtf8(rnRuntime, resultStr);
266
+ funPtr->call(rnRuntime, resultValue);
267
+ });
268
+ });
269
+ return jsi::Value::undefined();
270
+ }
271
+
272
+ jsi::Value ReanimatedModuleProxy::getStaticFeatureFlag(jsi::Runtime &rt, const jsi::Value &name) {
273
+ return reanimated::StaticFeatureFlags::getFlag(name.asString(rt).utf8(rt));
274
+ }
275
+
276
+ jsi::Value
277
+ ReanimatedModuleProxy::setDynamicFeatureFlag(jsi::Runtime &rt, const jsi::Value &name, const jsi::Value &value) {
278
+ reanimated::DynamicFeatureFlags::setFlag(name.asString(rt).utf8(rt), value.asBool());
279
+ return jsi::Value::undefined();
280
+ }
281
+
282
+ jsi::Value ReanimatedModuleProxy::configureLayoutAnimationBatch(
283
+ jsi::Runtime &rt,
284
+ const jsi::Value &layoutAnimationsBatch) {
285
+ auto array = layoutAnimationsBatch.asObject(rt).asArray(rt);
286
+ size_t length = array.size(rt);
287
+ std::vector<LayoutAnimationConfig> batch(length);
288
+ for (int i = 0; i < length; i++) {
289
+ auto item = array.getValueAtIndex(rt, i).asObject(rt);
290
+ auto &batchItem = batch[i];
291
+ batchItem.tag = item.getProperty(rt, "viewTag").asNumber();
292
+ batchItem.type = static_cast<LayoutAnimationType>(item.getProperty(rt, "type").asNumber());
293
+ auto config = item.getProperty(rt, "config");
294
+ if (config.isUndefined()) {
295
+ batchItem.config = nullptr;
296
+ } else {
297
+ batchItem.config = extractSerializableOrThrow<SerializableObject>(
298
+ rt, config, "[Reanimated] Layout animation config must be an object.");
299
+ }
300
+ auto sharedTag = item.getProperty(rt, "sharedTransitionTag");
301
+ if (!sharedTag.isUndefined()) {
302
+ batchItem.sharedTransitionTag = sharedTag.asString(rt).utf8(rt);
303
+ }
304
+ }
305
+ layoutAnimationsManager_->configureAnimationBatch(batch);
306
+ return jsi::Value::undefined();
307
+ }
308
+
309
+ void ReanimatedModuleProxy::setShouldAnimateExiting(
310
+ jsi::Runtime &rt,
311
+ const jsi::Value &viewTag,
312
+ const jsi::Value &shouldAnimate) {
313
+ layoutAnimationsManager_->setShouldAnimateExiting(viewTag.asNumber(), shouldAnimate.getBool());
314
+ }
315
+
316
+ bool ReanimatedModuleProxy::isAnyHandlerWaitingForEvent(const std::string &eventName, const int emitterReactTag) {
317
+ return eventHandlerRegistry_->isAnyHandlerWaitingForEvent(eventName, emitterReactTag);
318
+ }
319
+
320
+ void ReanimatedModuleProxy::maybeRequestRender() {
321
+ if (!renderRequested_) {
322
+ renderRequested_ = true;
323
+ requestRender_(onRenderCallback_);
324
+ }
325
+ }
326
+
327
+ void ReanimatedModuleProxy::onRender(double timestampMs) {
328
+ ReanimatedSystraceSection s("ReanimatedModuleProxy::onRender");
329
+ // NOOP
330
+ }
331
+
332
+ jsi::Value ReanimatedModuleProxy::registerSensor(
333
+ jsi::Runtime &rt,
334
+ const jsi::Value &sensorType,
335
+ const jsi::Value &interval,
336
+ const jsi::Value &iosReferenceFrame,
337
+ const jsi::Value &sensorDataHandler) {
338
+ return animatedSensorModule_.registerSensor(
339
+ rt, workletsModuleProxy_->getUIWorkletRuntime(), sensorType, interval, iosReferenceFrame, sensorDataHandler);
340
+ }
341
+
342
+ void ReanimatedModuleProxy::unregisterSensor(jsi::Runtime &, const jsi::Value &sensorId) {
343
+ animatedSensorModule_.unregisterSensor(sensorId);
344
+ }
345
+
346
+ void ReanimatedModuleProxy::cleanupSensors() {
347
+ animatedSensorModule_.unregisterAllSensors();
348
+ }
349
+
350
+ void ReanimatedModuleProxy::setViewStyle(jsi::Runtime &rt, const jsi::Value &viewTag, const jsi::Value &viewStyle) {
351
+ const auto tag = viewTag.asNumber();
352
+ staticPropsRegistry_->set(rt, tag, viewStyle);
353
+ if (staticPropsRegistry_->hasObservers(tag)) {
354
+ maybeRunCSSLoop();
355
+ }
356
+ }
357
+
358
+ void ReanimatedModuleProxy::markNodeAsRemovable(jsi::Runtime &rt, const jsi::Value &shadowNodeWrapper) {
359
+ auto lock = updatesRegistryManager_->lock();
360
+ auto shadowNode = shadowNodeFromValue(rt, shadowNodeWrapper);
361
+ updatesRegistryManager_->markNodeAsRemovable(shadowNode);
362
+ }
363
+
364
+ void ReanimatedModuleProxy::unmarkNodeAsRemovable(jsi::Runtime &rt, const jsi::Value &viewTag) {
365
+ auto lock = updatesRegistryManager_->lock();
366
+ updatesRegistryManager_->unmarkNodeAsRemovable(viewTag.asNumber());
367
+ }
368
+
369
+ void ReanimatedModuleProxy::registerCSSKeyframes(
370
+ jsi::Runtime &rt,
371
+ const jsi::Value &animationName,
372
+ const jsi::Value &viewName,
373
+ const jsi::Value &keyframesConfig) {
374
+ // Convert react view name to Fabric component name
375
+ const auto componentName = componentNameByReactViewName(viewName.asString(rt).utf8(rt));
376
+ cssAnimationKeyframesRegistry_->set(
377
+ animationName.asString(rt).utf8(rt),
378
+ componentName,
379
+ parseCSSAnimationKeyframesConfig(rt, keyframesConfig, componentName, viewStylesRepository_));
380
+ }
381
+
382
+ void ReanimatedModuleProxy::unregisterCSSKeyframes(
383
+ jsi::Runtime &rt,
384
+ const jsi::Value &animationName,
385
+ const jsi::Value &viewName) {
386
+ cssAnimationKeyframesRegistry_->remove(
387
+ animationName.asString(rt).utf8(rt), componentNameByReactViewName(viewName.asString(rt).utf8(rt)));
388
+ }
389
+
390
+ void ReanimatedModuleProxy::applyCSSAnimations(
391
+ jsi::Runtime &rt,
392
+ const jsi::Value &shadowNodeWrapper,
393
+ const jsi::Value &animationUpdates) {
394
+ auto shadowNode = shadowNodeFromValue(rt, shadowNodeWrapper);
395
+ const auto timestamp = getCssTimestamp();
396
+ const auto updates = parseCSSAnimationUpdates(rt, animationUpdates);
397
+
398
+ CSSAnimationsMap newAnimations;
399
+
400
+ if (!updates.newAnimationSettings.empty()) {
401
+ // animationNames always exists when newAnimationSettings is not empty
402
+ const auto animationNames = updates.animationNames.value();
403
+ const auto animationNamesCount = animationNames.size();
404
+
405
+ for (const auto &[index, settings] : updates.newAnimationSettings) {
406
+ if (index >= animationNamesCount) {
407
+ throw std::invalid_argument("[Reanimated] index is out of bounds of animationNames");
408
+ }
409
+
410
+ const auto &animationName = animationNames[index];
411
+ const auto &keyframesConfig = cssAnimationKeyframesRegistry_->get(animationName, shadowNode->getComponentName());
412
+
413
+ newAnimations.emplace(
414
+ index, std::make_shared<CSSAnimation>(rt, shadowNode, animationName, keyframesConfig, settings, timestamp));
415
+ }
416
+ }
417
+
418
+ {
419
+ auto lock = cssAnimationsRegistry_->lock();
420
+ cssAnimationsRegistry_->apply(
421
+ rt, shadowNode, updates.animationNames, newAnimations, updates.settingsUpdates, timestamp);
422
+ }
423
+
424
+ maybeRunCSSLoop();
425
+ }
426
+
427
+ void ReanimatedModuleProxy::unregisterCSSAnimations(const jsi::Value &viewTag) {
428
+ auto lock = cssAnimationsRegistry_->lock();
429
+ cssAnimationsRegistry_->remove(viewTag.asNumber());
430
+ }
431
+
432
+ void ReanimatedModuleProxy::registerCSSTransition(
433
+ jsi::Runtime &rt,
434
+ const jsi::Value &shadowNodeWrapper,
435
+ const jsi::Value &transitionConfig) {
436
+ auto shadowNode = shadowNodeFromValue(rt, shadowNodeWrapper);
437
+
438
+ auto transition = std::make_shared<CSSTransition>(
439
+ std::move(shadowNode), parseCSSTransitionConfig(rt, transitionConfig), viewStylesRepository_);
440
+
441
+ {
442
+ auto lock = cssTransitionsRegistry_->lock();
443
+ cssTransitionsRegistry_->add(transition);
444
+ }
445
+ maybeRunCSSLoop();
446
+ }
447
+
448
+ void ReanimatedModuleProxy::updateCSSTransition(
449
+ jsi::Runtime &rt,
450
+ const jsi::Value &viewTag,
451
+ const jsi::Value &configUpdates) {
452
+ auto lock = cssTransitionsRegistry_->lock();
453
+ cssTransitionsRegistry_->updateSettings(viewTag.asNumber(), parsePartialCSSTransitionConfig(rt, configUpdates));
454
+ maybeRunCSSLoop();
455
+ }
456
+
457
+ void ReanimatedModuleProxy::unregisterCSSTransition(jsi::Runtime &rt, const jsi::Value &viewTag) {
458
+ auto lock = cssTransitionsRegistry_->lock();
459
+ cssTransitionsRegistry_->remove(viewTag.asNumber());
460
+ }
461
+
462
+ jsi::Value ReanimatedModuleProxy::getSettledUpdates(jsi::Runtime &rt) {
463
+ react_native_assert(
464
+ StaticFeatureFlags::getFlag("FORCE_REACT_RENDER_FOR_SETTLED_ANIMATIONS") &&
465
+ "getSettledUpdates requires FORCE_REACT_RENDER_FOR_SETTLED_ANIMATIONS static feature flag to be enabled");
466
+
467
+ // TODO(future): use unified timestamp
468
+ const auto currentTimestamp = getAnimationTimestamp_();
469
+
470
+ const auto lock = animatedPropsRegistry_->lock();
471
+
472
+ // TODO: fix bug when threshold difference is smaller than 1 second
473
+ // TODO(future): flush updates from CSS animations and CSS transitions registries
474
+ animatedPropsRegistry_->removeUpdatesOlderThanTimestamp(currentTimestamp - 2000); // 2 seconds
475
+
476
+ // TODO(future): find a better way to obtain timestamp for removing updates
477
+ // TODO(future): move removing old updates to separate method
478
+ return animatedPropsRegistry_->getUpdatesOlderThanTimestamp(rt, currentTimestamp - 1000); // 1 second
479
+ }
480
+
481
+ bool ReanimatedModuleProxy::handleEvent(
482
+ const std::string &eventName,
483
+ const int emitterReactTag,
484
+ const jsi::Value &payload,
485
+ double currentTime) {
486
+ ReanimatedSystraceSection s("ReanimatedModuleProxy::handleEvent");
487
+
488
+ eventHandlerRegistry_->processEvent(
489
+ workletsModuleProxy_->getUIWorkletRuntime(), currentTime, eventName, emitterReactTag, payload);
490
+
491
+ // TODO: return true if Reanimated successfully handled the event
492
+ // to avoid sending it to JavaScript
493
+ return false;
494
+ }
495
+
496
+ bool ReanimatedModuleProxy::handleRawEvent(const RawEvent &rawEvent, double currentTime) {
497
+ ReanimatedSystraceSection s("ReanimatedModuleProxy::handleRawEvent");
498
+
499
+ const EventTarget *eventTarget = rawEvent.eventTarget.get();
500
+ if (eventTarget == nullptr) {
501
+ // after app reload scrollView is unmounted and its content offset is set
502
+ // to 0 and view is thrown into recycle pool setting content offset
503
+ // triggers scroll event eventTarget is null though, because it's
504
+ // unmounting we can just ignore this event, because it's an event on
505
+ // unmounted component
506
+ return false;
507
+ }
508
+
509
+ int tag = eventTarget->getTag();
510
+ auto eventType = rawEvent.type;
511
+ if (eventType.rfind("top", 0) == 0) {
512
+ eventType = "on" + eventType.substr(3);
513
+ }
514
+
515
+ if constexpr (StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS")) {
516
+ if (eventType == "onTransitionProgress") {
517
+ jsi::Runtime &rt = workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
518
+ const auto &eventPayload = rawEvent.eventPayload;
519
+ jsi::Object payload = eventPayload->asJSIValue(rt).asObject(rt);
520
+ auto progress = payload.getProperty(rt, "progress").asNumber();
521
+ auto closing = static_cast<bool>(payload.getProperty(rt, "closing").asNumber());
522
+ auto goingForward = static_cast<bool>(payload.getProperty(rt, "goingForward").asNumber());
523
+
524
+ if (!layoutAnimationsProxy_) {
525
+ return false;
526
+ }
527
+ auto surfaceId = layoutAnimationsProxy_->onTransitionProgress(tag, progress, closing, goingForward);
528
+ if (!surfaceId) {
529
+ return false;
530
+ }
531
+ // TODO (future): enumerate -> visit
532
+ uiManager_->getShadowTreeRegistry().enumerate(
533
+ [](const ShadowTree &shadowTree, bool &) { shadowTree.notifyDelegatesOfUpdates(); });
534
+ return false;
535
+ } else if (eventType == "onGestureCancel") {
536
+ if (!layoutAnimationsProxy_) {
537
+ return false;
538
+ }
539
+ auto surfaceId = layoutAnimationsProxy_->onGestureCancel();
540
+ if (!surfaceId) {
541
+ return false;
542
+ }
543
+ // TODO (future): enumerate -> visit
544
+ uiManager_->getShadowTreeRegistry().enumerate(
545
+ [](const ShadowTree &shadowTree, bool &) { shadowTree.notifyDelegatesOfUpdates(); });
546
+ return false;
547
+ }
548
+ }
549
+
550
+ if (!isAnyHandlerWaitingForEvent(eventType, tag)) {
551
+ return false;
552
+ }
553
+
554
+ jsi::Runtime &rt = workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
555
+ const auto &eventPayload = rawEvent.eventPayload;
556
+ jsi::Value payload = eventPayload->asJSIValue(rt);
557
+
558
+ auto res = handleEvent(eventType, tag, payload, currentTime);
559
+ // TODO: we should call performOperations conditionally if event is handled
560
+ // (res == true), but for now handleEvent always returns false. Thankfully,
561
+ // performOperations does not trigger a lot of code if there is nothing to
562
+ // be done so this is fine for now.
563
+ performOperations(true);
564
+ return res;
565
+ }
566
+
567
+ void ReanimatedModuleProxy::cssLoopCallback(const double /*timestampMs*/) {
568
+ shouldUpdateCssAnimations_ = true;
569
+ if (cssAnimationsRegistry_->hasUpdates() || cssTransitionsRegistry_->hasUpdates()
570
+ #ifdef ANDROID
571
+ || updatesRegistryManager_->hasPropsToRevert()
572
+ #endif // ANDROID
573
+ ) {
574
+ requestRender_([weakThis = weak_from_this()](const double newTimestampMs) {
575
+ if (auto strongThis = weakThis.lock()) {
576
+ strongThis->cssLoopCallback(newTimestampMs);
577
+ }
578
+ });
579
+ } else {
580
+ cssLoopRunning_ = false;
581
+ }
582
+ }
583
+
584
+ void ReanimatedModuleProxy::maybeRunCSSLoop() {
585
+ if (cssLoopRunning_) {
586
+ return;
587
+ }
588
+
589
+ cssLoopRunning_ = true;
590
+
591
+ workletsModuleProxy_->getUIScheduler()->scheduleOnUI([weakThis = weak_from_this()]() {
592
+ auto strongThis = weakThis.lock();
593
+ if (!strongThis) {
594
+ return;
595
+ }
596
+ strongThis->requestRender_([weakThis](const double timestampMs) {
597
+ if (auto strongThis = weakThis.lock()) {
598
+ strongThis->cssLoopCallback(timestampMs);
599
+ }
600
+ });
601
+ });
602
+ }
603
+
604
+ double ReanimatedModuleProxy::getCssTimestamp() {
605
+ if (cssLoopRunning_) {
606
+ return currentCssTimestamp_;
607
+ }
608
+ currentCssTimestamp_ = getAnimationTimestamp_();
609
+ return currentCssTimestamp_;
610
+ }
611
+
612
+ void ReanimatedModuleProxy::performOperations(const bool isTriggeredByEvent) {
613
+ ReanimatedSystraceSection s("ReanimatedModuleProxy::performOperations");
614
+
615
+ if (!isTriggeredByEvent) {
616
+ auto flushRequestsCopy = std::move(layoutAnimationFlushRequests_);
617
+ for (const auto surfaceId : flushRequestsCopy) {
618
+ uiManager_->getShadowTreeRegistry().visit(
619
+ surfaceId, [](const ShadowTree &shadowTree) { shadowTree.notifyDelegatesOfUpdates(); });
620
+ }
621
+ }
622
+
623
+ jsi::Runtime &rt = workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
624
+
625
+ UpdatesBatch updatesBatch;
626
+ {
627
+ ReanimatedSystraceSection s2("ReanimatedModuleProxy::flushUpdates");
628
+
629
+ auto lock = updatesRegistryManager_->lock();
630
+
631
+ if (shouldUpdateCssAnimations_) {
632
+ currentCssTimestamp_ = getAnimationTimestamp_();
633
+ auto lock = cssTransitionsRegistry_->lock();
634
+ // Update CSS transitions and flush updates
635
+ cssTransitionsRegistry_->update(currentCssTimestamp_);
636
+ cssTransitionsRegistry_->flushUpdates(updatesBatch);
637
+ }
638
+
639
+ {
640
+ auto lock = animatedPropsRegistry_->lock();
641
+ // Flush all animated props updates
642
+ animatedPropsRegistry_->flushUpdates(updatesBatch);
643
+ }
644
+
645
+ if (shouldUpdateCssAnimations_) {
646
+ auto lock = cssAnimationsRegistry_->lock();
647
+ // Update CSS animations and flush updates
648
+ cssAnimationsRegistry_->update(currentCssTimestamp_);
649
+ cssAnimationsRegistry_->flushUpdates(updatesBatch);
650
+ }
651
+
652
+ shouldUpdateCssAnimations_ = false;
653
+
654
+ #ifdef ANDROID
655
+ if constexpr (
656
+ StaticFeatureFlags::getFlag("ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS") &&
657
+ !StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS")) {
658
+ static const std::unordered_set<std::string> synchronousProps = {
659
+ "opacity",
660
+ "elevation",
661
+ "zIndex",
662
+ // "shadowOpacity", // not supported on Android
663
+ // "shadowRadius", // not supported on Android
664
+ "backgroundColor",
665
+ // "color", // TODO: fix animating color of Animated.Text
666
+ "tintColor",
667
+ "borderRadius",
668
+ "borderTopLeftRadius",
669
+ "borderTopRightRadius",
670
+ "borderTopStartRadius",
671
+ "borderTopEndRadius",
672
+ "borderBottomLeftRadius",
673
+ "borderBottomRightRadius",
674
+ "borderBottomStartRadius",
675
+ "borderBottomEndRadius",
676
+ "borderStartStartRadius",
677
+ "borderStartEndRadius",
678
+ "borderEndStartRadius",
679
+ "borderEndEndRadius",
680
+ "borderColor",
681
+ "borderTopColor",
682
+ "borderBottomColor",
683
+ "borderLeftColor",
684
+ "borderRightColor",
685
+ "borderStartColor",
686
+ "borderEndColor",
687
+ "transform",
688
+ };
689
+
690
+ // NOTE: Keep in sync with NativeProxy.java
691
+ static constexpr auto CMD_START_OF_VIEW = 1;
692
+ static constexpr auto CMD_START_OF_TRANSFORM = 2;
693
+ static constexpr auto CMD_END_OF_TRANSFORM = 3;
694
+ static constexpr auto CMD_END_OF_VIEW = 4;
695
+
696
+ static constexpr auto CMD_OPACITY = 10;
697
+ static constexpr auto CMD_ELEVATION = 11;
698
+ static constexpr auto CMD_Z_INDEX = 12;
699
+ static constexpr auto CMD_SHADOW_OPACITY = 13;
700
+ static constexpr auto CMD_SHADOW_RADIUS = 14;
701
+ static constexpr auto CMD_BACKGROUND_COLOR = 15;
702
+ static constexpr auto CMD_COLOR = 16;
703
+ static constexpr auto CMD_TINT_COLOR = 17;
704
+
705
+ static constexpr auto CMD_BORDER_RADIUS = 20;
706
+ static constexpr auto CMD_BORDER_TOP_LEFT_RADIUS = 21;
707
+ static constexpr auto CMD_BORDER_TOP_RIGHT_RADIUS = 22;
708
+ static constexpr auto CMD_BORDER_TOP_START_RADIUS = 23;
709
+ static constexpr auto CMD_BORDER_TOP_END_RADIUS = 24;
710
+ static constexpr auto CMD_BORDER_BOTTOM_LEFT_RADIUS = 25;
711
+ static constexpr auto CMD_BORDER_BOTTOM_RIGHT_RADIUS = 26;
712
+ static constexpr auto CMD_BORDER_BOTTOM_START_RADIUS = 27;
713
+ static constexpr auto CMD_BORDER_BOTTOM_END_RADIUS = 28;
714
+ static constexpr auto CMD_BORDER_START_START_RADIUS = 29;
715
+ static constexpr auto CMD_BORDER_START_END_RADIUS = 30;
716
+ static constexpr auto CMD_BORDER_END_START_RADIUS = 31;
717
+ static constexpr auto CMD_BORDER_END_END_RADIUS = 32;
718
+
719
+ static constexpr auto CMD_BORDER_COLOR = 40;
720
+ static constexpr auto CMD_BORDER_TOP_COLOR = 41;
721
+ static constexpr auto CMD_BORDER_BOTTOM_COLOR = 42;
722
+ static constexpr auto CMD_BORDER_LEFT_COLOR = 43;
723
+ static constexpr auto CMD_BORDER_RIGHT_COLOR = 44;
724
+ static constexpr auto CMD_BORDER_START_COLOR = 45;
725
+ static constexpr auto CMD_BORDER_END_COLOR = 46;
726
+
727
+ static constexpr auto CMD_TRANSFORM_TRANSLATE_X = 100;
728
+ static constexpr auto CMD_TRANSFORM_TRANSLATE_Y = 101;
729
+ static constexpr auto CMD_TRANSFORM_SCALE = 102;
730
+ static constexpr auto CMD_TRANSFORM_SCALE_X = 103;
731
+ static constexpr auto CMD_TRANSFORM_SCALE_Y = 104;
732
+ static constexpr auto CMD_TRANSFORM_ROTATE = 105;
733
+ static constexpr auto CMD_TRANSFORM_ROTATE_X = 106;
734
+ static constexpr auto CMD_TRANSFORM_ROTATE_Y = 107;
735
+ static constexpr auto CMD_TRANSFORM_ROTATE_Z = 108;
736
+ static constexpr auto CMD_TRANSFORM_SKEW_X = 109;
737
+ static constexpr auto CMD_TRANSFORM_SKEW_Y = 110;
738
+ static constexpr auto CMD_TRANSFORM_MATRIX = 111;
739
+ static constexpr auto CMD_TRANSFORM_PERSPECTIVE = 112;
740
+
741
+ static constexpr auto CMD_UNIT_DEG = 200;
742
+ static constexpr auto CMD_UNIT_RAD = 201;
743
+ static constexpr auto CMD_UNIT_PX = 202;
744
+ static constexpr auto CMD_UNIT_PERCENT = 203;
745
+
746
+ const auto propNameToCommand = [](const std::string &name) {
747
+ if (name == "opacity")
748
+ return CMD_OPACITY;
749
+
750
+ if (name == "elevation")
751
+ return CMD_ELEVATION;
752
+
753
+ if (name == "zIndex")
754
+ return CMD_Z_INDEX;
755
+
756
+ if (name == "shadowOpacity")
757
+ return CMD_SHADOW_OPACITY;
758
+
759
+ if (name == "shadowRadius")
760
+ return CMD_SHADOW_RADIUS;
761
+
762
+ if (name == "backgroundColor")
763
+ return CMD_BACKGROUND_COLOR;
764
+
765
+ if (name == "color")
766
+ return CMD_COLOR;
767
+
768
+ if (name == "tintColor")
769
+ return CMD_TINT_COLOR;
770
+
771
+ if (name == "borderRadius")
772
+ return CMD_BORDER_RADIUS;
773
+
774
+ if (name == "borderTopLeftRadius")
775
+ return CMD_BORDER_TOP_LEFT_RADIUS;
776
+
777
+ if (name == "borderTopRightRadius")
778
+ return CMD_BORDER_TOP_RIGHT_RADIUS;
779
+
780
+ if (name == "borderTopStartRadius")
781
+ return CMD_BORDER_TOP_START_RADIUS;
782
+
783
+ if (name == "borderTopEndRadius")
784
+ return CMD_BORDER_TOP_END_RADIUS;
785
+
786
+ if (name == "borderBottomLeftRadius")
787
+ return CMD_BORDER_BOTTOM_LEFT_RADIUS;
788
+
789
+ if (name == "borderBottomRightRadius")
790
+ return CMD_BORDER_BOTTOM_RIGHT_RADIUS;
791
+
792
+ if (name == "borderBottomStartRadius")
793
+ return CMD_BORDER_BOTTOM_START_RADIUS;
794
+
795
+ if (name == "borderBottomEndRadius")
796
+ return CMD_BORDER_BOTTOM_END_RADIUS;
797
+
798
+ if (name == "borderStartStartRadius")
799
+ return CMD_BORDER_START_START_RADIUS;
800
+
801
+ if (name == "borderStartEndRadius")
802
+ return CMD_BORDER_START_END_RADIUS;
803
+
804
+ if (name == "borderEndStartRadius")
805
+ return CMD_BORDER_END_START_RADIUS;
806
+
807
+ if (name == "borderEndEndRadius")
808
+ return CMD_BORDER_END_END_RADIUS;
809
+
810
+ if (name == "borderColor")
811
+ return CMD_BORDER_COLOR;
812
+
813
+ if (name == "borderTopColor")
814
+ return CMD_BORDER_TOP_COLOR;
815
+
816
+ if (name == "borderBottomColor")
817
+ return CMD_BORDER_BOTTOM_COLOR;
818
+
819
+ if (name == "borderLeftColor")
820
+ return CMD_BORDER_LEFT_COLOR;
821
+
822
+ if (name == "borderRightColor")
823
+ return CMD_BORDER_RIGHT_COLOR;
824
+
825
+ if (name == "borderStartColor")
826
+ return CMD_BORDER_START_COLOR;
827
+
828
+ if (name == "borderEndColor")
829
+ return CMD_BORDER_END_COLOR;
830
+
831
+ if (name == "transform")
832
+ return CMD_START_OF_TRANSFORM; // TODO: use CMD_TRANSFORM?
833
+
834
+ throw std::runtime_error("[Reanimated] Unsupported style: " + name);
835
+ };
836
+
837
+ const auto transformNameToCommand = [](const std::string &name) {
838
+ if (name == "translateX")
839
+ return CMD_TRANSFORM_TRANSLATE_X;
840
+
841
+ if (name == "translateY")
842
+ return CMD_TRANSFORM_TRANSLATE_Y;
843
+
844
+ if (name == "scale")
845
+ return CMD_TRANSFORM_SCALE;
846
+
847
+ if (name == "scaleX")
848
+ return CMD_TRANSFORM_SCALE_X;
849
+
850
+ if (name == "scaleY")
851
+ return CMD_TRANSFORM_SCALE_Y;
852
+
853
+ if (name == "rotate")
854
+ return CMD_TRANSFORM_ROTATE;
855
+
856
+ if (name == "rotateX")
857
+ return CMD_TRANSFORM_ROTATE_X;
858
+
859
+ if (name == "rotateY")
860
+ return CMD_TRANSFORM_ROTATE_Y;
861
+
862
+ if (name == "rotateZ")
863
+ return CMD_TRANSFORM_ROTATE_Z;
864
+
865
+ if (name == "skewX")
866
+ return CMD_TRANSFORM_SKEW_X;
867
+
868
+ if (name == "skewY")
869
+ return CMD_TRANSFORM_SKEW_Y;
870
+
871
+ if (name == "matrix")
872
+ return CMD_TRANSFORM_MATRIX;
873
+
874
+ if (name == "perspective")
875
+ return CMD_TRANSFORM_PERSPECTIVE;
876
+
877
+ throw std::runtime_error("[Reanimated] Unsupported transform: " + name);
878
+ };
879
+
880
+ UpdatesBatch synchronousUpdatesBatch, shadowTreeUpdatesBatch;
881
+
882
+ for (const auto &[shadowNode, props] : updatesBatch) {
883
+ bool hasOnlySynchronousProps = true;
884
+ for (const auto &[key, value] : props.items()) {
885
+ const auto keyStr = key.asString();
886
+ if (!synchronousProps.contains(keyStr) ||
887
+ ((keyStr == "color" || keyStr.find("Color") != std::string::npos) && !value.isInt())) {
888
+ hasOnlySynchronousProps = false;
889
+ break;
890
+ }
891
+ }
892
+ if (hasOnlySynchronousProps) {
893
+ synchronousUpdatesBatch.emplace_back(shadowNode, props);
894
+ } else {
895
+ shadowTreeUpdatesBatch.emplace_back(shadowNode, props);
896
+ }
897
+ }
898
+
899
+ if (!synchronousUpdatesBatch.empty()) {
900
+ std::vector<int> intBuffer;
901
+ std::vector<double> doubleBuffer;
902
+ intBuffer.reserve(1024);
903
+ doubleBuffer.reserve(1024);
904
+
905
+ for (const auto &[shadowNode, props] : synchronousUpdatesBatch) {
906
+ intBuffer.push_back(CMD_START_OF_VIEW);
907
+ intBuffer.push_back(shadowNode->getTag());
908
+ for (const auto &[key, value] : props.items()) {
909
+ const auto command = propNameToCommand(key.getString());
910
+ switch (command) {
911
+ case CMD_OPACITY:
912
+ case CMD_ELEVATION:
913
+ case CMD_Z_INDEX:
914
+ case CMD_SHADOW_OPACITY:
915
+ case CMD_SHADOW_RADIUS:
916
+ intBuffer.push_back(command);
917
+ doubleBuffer.push_back(value.asDouble());
918
+ break;
919
+
920
+ case CMD_BACKGROUND_COLOR:
921
+ case CMD_COLOR:
922
+ case CMD_TINT_COLOR:
923
+ case CMD_BORDER_COLOR:
924
+ case CMD_BORDER_TOP_COLOR:
925
+ case CMD_BORDER_BOTTOM_COLOR:
926
+ case CMD_BORDER_LEFT_COLOR:
927
+ case CMD_BORDER_RIGHT_COLOR:
928
+ case CMD_BORDER_START_COLOR:
929
+ case CMD_BORDER_END_COLOR:
930
+ intBuffer.push_back(command);
931
+ intBuffer.push_back(value.asInt());
932
+ break;
933
+
934
+ case CMD_BORDER_RADIUS:
935
+ case CMD_BORDER_TOP_LEFT_RADIUS:
936
+ case CMD_BORDER_TOP_RIGHT_RADIUS:
937
+ case CMD_BORDER_TOP_START_RADIUS:
938
+ case CMD_BORDER_TOP_END_RADIUS:
939
+ case CMD_BORDER_BOTTOM_LEFT_RADIUS:
940
+ case CMD_BORDER_BOTTOM_RIGHT_RADIUS:
941
+ case CMD_BORDER_BOTTOM_START_RADIUS:
942
+ case CMD_BORDER_BOTTOM_END_RADIUS:
943
+ case CMD_BORDER_START_START_RADIUS:
944
+ case CMD_BORDER_START_END_RADIUS:
945
+ case CMD_BORDER_END_START_RADIUS:
946
+ case CMD_BORDER_END_END_RADIUS:
947
+ intBuffer.push_back(command);
948
+ if (value.isDouble()) {
949
+ intBuffer.push_back(CMD_UNIT_PX);
950
+ doubleBuffer.push_back(value.getDouble());
951
+ } else if (value.isString()) {
952
+ const auto &valueStr = value.getString();
953
+ if (!valueStr.ends_with("%")) {
954
+ throw std::runtime_error("[Reanimated] Border radius string must be a percentage");
955
+ }
956
+ intBuffer.push_back(CMD_UNIT_PERCENT);
957
+ doubleBuffer.push_back(std::stof(valueStr.substr(0, -1)));
958
+ } else {
959
+ throw std::runtime_error("[Reanimated] Border radius value must be either a number or a string");
960
+ }
961
+ break;
962
+
963
+ case CMD_START_OF_TRANSFORM:
964
+ intBuffer.push_back(command);
965
+ react_native_assert(value.isArray() && "[Reanimated] Transform value must be an array");
966
+ for (const auto &item : value) {
967
+ react_native_assert(item.isObject() && "[Reanimated] Transform array item must be an object");
968
+ react_native_assert(
969
+ item.size() == 1 && "[Reanimated] Transform array item must have exactly one key-value pair");
970
+ const auto transformCommand = transformNameToCommand(item.keys().begin()->getString());
971
+ const auto &transformValue = *item.values().begin();
972
+ switch (transformCommand) {
973
+ case CMD_TRANSFORM_SCALE:
974
+ case CMD_TRANSFORM_SCALE_X:
975
+ case CMD_TRANSFORM_SCALE_Y:
976
+ case CMD_TRANSFORM_PERSPECTIVE: {
977
+ intBuffer.push_back(transformCommand);
978
+ doubleBuffer.push_back(transformValue.asDouble());
979
+ break;
980
+ }
981
+
982
+ case CMD_TRANSFORM_TRANSLATE_X:
983
+ case CMD_TRANSFORM_TRANSLATE_Y: {
984
+ intBuffer.push_back(transformCommand);
985
+ if (transformValue.isDouble()) {
986
+ intBuffer.push_back(CMD_UNIT_PX);
987
+ doubleBuffer.push_back(transformValue.getDouble());
988
+ } else if (transformValue.isString()) {
989
+ const auto &transformValueStr = transformValue.getString();
990
+ if (!transformValueStr.ends_with("%")) {
991
+ throw std::runtime_error("[Reanimated] String translate must be a percentage");
992
+ }
993
+ intBuffer.push_back(CMD_UNIT_PERCENT);
994
+ doubleBuffer.push_back(std::stof(transformValueStr.substr(0, -1)));
995
+ } else {
996
+ throw std::runtime_error("[Reanimated] Translate value must be either a number or a string");
997
+ }
998
+ break;
999
+ }
1000
+
1001
+ case CMD_TRANSFORM_ROTATE:
1002
+ case CMD_TRANSFORM_ROTATE_X:
1003
+ case CMD_TRANSFORM_ROTATE_Y:
1004
+ case CMD_TRANSFORM_ROTATE_Z:
1005
+ case CMD_TRANSFORM_SKEW_X:
1006
+ case CMD_TRANSFORM_SKEW_Y: {
1007
+ const auto &transformValueStr = transformValue.getString();
1008
+ intBuffer.push_back(transformCommand);
1009
+ if (transformValueStr.ends_with("deg")) {
1010
+ intBuffer.push_back(CMD_UNIT_DEG);
1011
+ } else if (transformValueStr.ends_with("rad")) {
1012
+ intBuffer.push_back(CMD_UNIT_RAD);
1013
+ } else {
1014
+ throw std::runtime_error("[Reanimated] Unsupported rotation unit: " + transformValueStr);
1015
+ }
1016
+ doubleBuffer.push_back(std::stof(transformValueStr.substr(0, -3)));
1017
+ break;
1018
+ }
1019
+
1020
+ case CMD_TRANSFORM_MATRIX: {
1021
+ intBuffer.push_back(transformCommand);
1022
+ react_native_assert(transformValue.isArray() && "[Reanimated] Matrix must be an array");
1023
+ int size = transformValue.size();
1024
+ intBuffer.push_back(size);
1025
+ for (int i = 0; i < size; i++) {
1026
+ doubleBuffer.push_back(transformValue[i].asDouble());
1027
+ }
1028
+ break;
1029
+ }
1030
+ }
1031
+ }
1032
+ intBuffer.push_back(CMD_END_OF_TRANSFORM);
1033
+ break;
1034
+ }
1035
+ }
1036
+ intBuffer.push_back(CMD_END_OF_VIEW);
1037
+ }
1038
+ synchronouslyUpdateUIPropsFunction_(intBuffer, doubleBuffer);
1039
+ }
1040
+
1041
+ updatesBatch = std::move(shadowTreeUpdatesBatch);
1042
+ }
1043
+ #endif // ANDROID
1044
+
1045
+ #if __APPLE__
1046
+ if constexpr (
1047
+ StaticFeatureFlags::getFlag("IOS_SYNCHRONOUSLY_UPDATE_UI_PROPS") &&
1048
+ !StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS")) {
1049
+ static const std::unordered_set<std::string> synchronousProps = {
1050
+ "opacity",
1051
+ "elevation",
1052
+ "zIndex",
1053
+ "shadowOpacity",
1054
+ "shadowRadius",
1055
+ "backgroundColor",
1056
+ // "color", // TODO: fix animating color of Animated.Text
1057
+ "tintColor",
1058
+ "borderRadius",
1059
+ "borderTopLeftRadius",
1060
+ "borderTopRightRadius",
1061
+ "borderTopStartRadius",
1062
+ "borderTopEndRadius",
1063
+ "borderBottomLeftRadius",
1064
+ "borderBottomRightRadius",
1065
+ "borderBottomStartRadius",
1066
+ "borderBottomEndRadius",
1067
+ "borderStartStartRadius",
1068
+ "borderStartEndRadius",
1069
+ "borderEndStartRadius",
1070
+ "borderEndEndRadius",
1071
+ "borderColor",
1072
+ "borderTopColor",
1073
+ "borderBottomColor",
1074
+ "borderLeftColor",
1075
+ "borderRightColor",
1076
+ "borderStartColor",
1077
+ "borderEndColor",
1078
+ "transform",
1079
+ };
1080
+
1081
+ UpdatesBatch synchronousUpdatesBatch, shadowTreeUpdatesBatch;
1082
+
1083
+ for (const auto &[shadowNode, props] : updatesBatch) {
1084
+ bool hasOnlySynchronousProps = true;
1085
+ for (const auto &key : props.keys()) {
1086
+ const auto keyStr = key.asString();
1087
+ if (!synchronousProps.contains(keyStr)) {
1088
+ hasOnlySynchronousProps = false;
1089
+ break;
1090
+ }
1091
+ }
1092
+ if (hasOnlySynchronousProps) {
1093
+ synchronousUpdatesBatch.emplace_back(shadowNode, props);
1094
+ } else {
1095
+ shadowTreeUpdatesBatch.emplace_back(shadowNode, props);
1096
+ }
1097
+ }
1098
+
1099
+ for (const auto &[shadowNode, props] : synchronousUpdatesBatch) {
1100
+ synchronouslyUpdateUIPropsFunction_(shadowNode->getTag(), props);
1101
+ }
1102
+
1103
+ updatesBatch = std::move(shadowTreeUpdatesBatch);
1104
+ }
1105
+ #endif // __APPLE__
1106
+
1107
+ if ((updatesBatch.size() > 0) && updatesRegistryManager_->shouldReanimatedSkipCommit()) {
1108
+ updatesRegistryManager_->pleaseCommitAfterPause();
1109
+ }
1110
+ }
1111
+
1112
+ if (updatesRegistryManager_->shouldReanimatedSkipCommit()) {
1113
+ // It may happen that `performOperations` is called on the UI thread
1114
+ // while React Native tries to commit a new tree on the JS thread.
1115
+ // In this case, we should skip the commit here and let React Native do
1116
+ // it. The commit will include the current values from the updates manager
1117
+ // which will be applied in ReanimatedCommitHook.
1118
+ return;
1119
+ }
1120
+
1121
+ commitUpdates(rt, updatesBatch);
1122
+
1123
+ // Clear the entire cache after the commit
1124
+ // (we don't know if the view is updated from outside of Reanimated
1125
+ // so we have to clear the entire cache)
1126
+ viewStylesRepository_->clearNodesCache();
1127
+ }
1128
+
1129
+ void ReanimatedModuleProxy::requestFlushRegistry() {
1130
+ requestRender_([weakThis = weak_from_this()](const double timestamp) {
1131
+ if (auto strongThis = weakThis.lock()) {
1132
+ strongThis->shouldFlushRegistry_ = true;
1133
+ }
1134
+ });
1135
+ }
1136
+
1137
+ void ReanimatedModuleProxy::commitUpdates(jsi::Runtime &rt, const UpdatesBatch &updatesBatch) {
1138
+ ReanimatedSystraceSection s("ReanimatedModuleProxy::commitUpdates");
1139
+ react_native_assert(uiManager_ != nullptr);
1140
+ const auto &shadowTreeRegistry = uiManager_->getShadowTreeRegistry();
1141
+
1142
+ std::unordered_map<SurfaceId, PropsMap> propsMapBySurface;
1143
+
1144
+ #ifdef ANDROID
1145
+ updatesRegistryManager_->collectPropsToRevertBySurface(propsMapBySurface);
1146
+ #endif
1147
+
1148
+ if (shouldFlushRegistry_) {
1149
+ shouldFlushRegistry_ = false;
1150
+ const auto propsMap = updatesRegistryManager_->collectProps();
1151
+ for (auto const &[family, props] : propsMap) {
1152
+ const auto surfaceId = family->getSurfaceId();
1153
+ auto &propsVector = propsMapBySurface[surfaceId][family];
1154
+ for (const auto &prop : props) {
1155
+ propsVector.emplace_back(prop);
1156
+ }
1157
+ }
1158
+ } else {
1159
+ for (auto const &[shadowNode, props] : updatesBatch) {
1160
+ SurfaceId surfaceId = shadowNode->getSurfaceId();
1161
+ auto family = &shadowNode->getFamily();
1162
+ react_native_assert(family->getSurfaceId() == surfaceId);
1163
+ propsMapBySurface[surfaceId][family].emplace_back(props);
1164
+ }
1165
+ }
1166
+
1167
+ for (const auto &entry : propsMapBySurface) {
1168
+ const SurfaceId surfaceId = entry.first;
1169
+ const PropsMap &propsMap = entry.second;
1170
+ shadowTreeRegistry.visit(surfaceId, [&](ShadowTree const &shadowTree) {
1171
+ const auto status = shadowTree.commit(
1172
+ [&](RootShadowNode const &oldRootShadowNode) -> RootShadowNode::Unshared {
1173
+ if (updatesRegistryManager_->shouldReanimatedSkipCommit()) {
1174
+ return nullptr;
1175
+ }
1176
+
1177
+ auto rootNode = cloneShadowTreeWithNewProps(oldRootShadowNode, propsMap);
1178
+
1179
+ // Mark the commit as Reanimated commit so that we can distinguish
1180
+ // it in ReanimatedCommitHook.
1181
+
1182
+ auto reaShadowNode = std::reinterpret_pointer_cast<ReanimatedCommitShadowNode>(rootNode);
1183
+ reaShadowNode->setReanimatedCommitTrait();
1184
+
1185
+ return rootNode;
1186
+ },
1187
+ {/* .enableStateReconciliation = */
1188
+ false,
1189
+ /* .mountSynchronously = */ true});
1190
+
1191
+ #ifdef ANDROID
1192
+ if (status == ShadowTree::CommitStatus::Succeeded) {
1193
+ updatesRegistryManager_->clearPropsToRevert(surfaceId);
1194
+ }
1195
+ #else
1196
+ (void)status;
1197
+ #endif
1198
+ });
1199
+ }
1200
+ }
1201
+
1202
+ void ReanimatedModuleProxy::dispatchCommand(
1203
+ jsi::Runtime &rt,
1204
+ const jsi::Value &shadowNodeValue,
1205
+ const jsi::Value &commandNameValue,
1206
+ const jsi::Value &argsValue) {
1207
+ const auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
1208
+ std::string commandName = stringFromValue(rt, commandNameValue);
1209
+ folly::dynamic args = commandArgsFromValue(rt, argsValue);
1210
+ const auto &scheduler = static_cast<Scheduler *>(uiManager_->getDelegate());
1211
+
1212
+ if (!scheduler) {
1213
+ return;
1214
+ }
1215
+
1216
+ const auto &schedulerDelegate = scheduler->getDelegate();
1217
+
1218
+ if (schedulerDelegate) {
1219
+ const auto shadowView = ShadowView(*shadowNode);
1220
+ schedulerDelegate->schedulerDidDispatchCommand(shadowView, commandName, args);
1221
+ }
1222
+ }
1223
+
1224
+ jsi::String
1225
+ ReanimatedModuleProxy::obtainProp(jsi::Runtime &rt, const jsi::Value &shadowNodeWrapper, const jsi::Value &propName) {
1226
+ jsi::Runtime &uiRuntime = workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
1227
+ const auto propNameStr = propName.asString(rt).utf8(rt);
1228
+ const auto shadowNode = shadowNodeFromValue(rt, shadowNodeWrapper);
1229
+ const auto resultStr = obtainPropFromShadowNode(uiRuntime, propNameStr, shadowNode);
1230
+ return jsi::String::createFromUtf8(rt, resultStr);
1231
+ }
1232
+
1233
+ jsi::Value ReanimatedModuleProxy::measure(jsi::Runtime &rt, const jsi::Value &shadowNodeValue) {
1234
+ // based on implementation from UIManagerBinding.cpp
1235
+
1236
+ auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
1237
+ auto layoutMetrics = uiManager_->getRelativeLayoutMetrics(*shadowNode, nullptr, {/* .includeTransform = */ true});
1238
+
1239
+ if (layoutMetrics == EmptyLayoutMetrics) {
1240
+ // Originally, in this case React Native returns `{0, 0, 0, 0, 0, 0}`,
1241
+ // most likely due to the type of measure callback function which accepts
1242
+ // just an array of numbers (not null). In Reanimated, `measure` returns
1243
+ // `MeasuredDimensions | null`.
1244
+ return jsi::Value::null();
1245
+ }
1246
+ auto newestCloneOfShadowNode = uiManager_->getNewestCloneOfShadowNode(*shadowNode);
1247
+
1248
+ auto layoutableShadowNode = dynamic_cast<LayoutableShadowNode const *>(newestCloneOfShadowNode.get());
1249
+ facebook::react::Point originRelativeToParent = layoutableShadowNode != nullptr
1250
+ ? layoutableShadowNode->getLayoutMetrics().frame.origin
1251
+ : facebook::react::Point();
1252
+
1253
+ auto frame = layoutMetrics.frame;
1254
+
1255
+ jsi::Object result(rt);
1256
+ result.setProperty(rt, "x", jsi::Value(static_cast<double>(originRelativeToParent.x)));
1257
+ result.setProperty(rt, "y", jsi::Value(static_cast<double>(originRelativeToParent.y)));
1258
+ result.setProperty(rt, "width", jsi::Value(static_cast<double>(frame.size.width)));
1259
+ result.setProperty(rt, "height", jsi::Value(static_cast<double>(frame.size.height)));
1260
+ result.setProperty(rt, "pageX", jsi::Value(static_cast<double>(frame.origin.x)));
1261
+ result.setProperty(rt, "pageY", jsi::Value(static_cast<double>(frame.origin.y)));
1262
+ return result;
1263
+ }
1264
+
1265
+ void ReanimatedModuleProxy::initializeFabric(const std::shared_ptr<UIManager> &uiManager) {
1266
+ uiManager_ = uiManager;
1267
+ viewStylesRepository_->setUIManager(uiManager_);
1268
+
1269
+ initializeLayoutAnimationsProxy();
1270
+
1271
+ const std::function<void()> request = [weakThis = weak_from_this()]() {
1272
+ auto strongThis = weakThis.lock();
1273
+ if (!strongThis) {
1274
+ return;
1275
+ }
1276
+
1277
+ strongThis->requestFlushRegistry();
1278
+ };
1279
+ mountHook_ = std::make_shared<ReanimatedMountHook>(uiManager_, updatesRegistryManager_, request);
1280
+ commitHook_ = std::make_shared<ReanimatedCommitHook>(uiManager_, updatesRegistryManager_, layoutAnimationsProxy_);
1281
+ }
1282
+
1283
+ void ReanimatedModuleProxy::initializeLayoutAnimationsProxy() {
1284
+ auto scheduler = reinterpret_cast<Scheduler *>(uiManager_->getDelegate());
1285
+ auto componentDescriptorRegistry =
1286
+ scheduler->getContextContainer()
1287
+ ->at<std::weak_ptr<const ComponentDescriptorRegistry>>("ComponentDescriptorRegistry_DO_NOT_USE_PRETTY_PLEASE")
1288
+ .lock();
1289
+
1290
+ if (componentDescriptorRegistry) {
1291
+ if constexpr (StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS")) {
1292
+ auto layoutAnimationsProxyExperimental = std::make_shared<LayoutAnimationsProxy_Experimental>(
1293
+ layoutAnimationsManager_,
1294
+ componentDescriptorRegistry,
1295
+ scheduler->getContextContainer(),
1296
+ workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime(),
1297
+ workletsModuleProxy_->getUIScheduler()
1298
+ #ifdef ANDROID
1299
+ ,
1300
+ filterUnmountedTagsFunction_,
1301
+ uiManager_,
1302
+ jsInvoker_
1303
+ #endif
1304
+ );
1305
+ #ifdef __APPLE__
1306
+ layoutAnimationsProxyExperimental->setForceScreenSnapshotFunction(forceScreenSnapshot_);
1307
+ #endif
1308
+ layoutAnimationsProxy_ = std::move(layoutAnimationsProxyExperimental);
1309
+ } else {
1310
+ auto layoutAnimationsProxyLegacy = std::make_shared<LayoutAnimationsProxy_Legacy>(
1311
+ layoutAnimationsManager_,
1312
+ componentDescriptorRegistry,
1313
+ scheduler->getContextContainer(),
1314
+ workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime(),
1315
+ workletsModuleProxy_->getUIScheduler()
1316
+ #ifdef ANDROID
1317
+ ,
1318
+ filterUnmountedTagsFunction_,
1319
+ uiManager_,
1320
+ jsInvoker_
1321
+ #endif
1322
+ );
1323
+ // TODO (future): support in experimental
1324
+ uiManager_->setAnimationDelegate(layoutAnimationsProxyLegacy.get());
1325
+ layoutAnimationsProxy_ = std::move(layoutAnimationsProxyLegacy);
1326
+ }
1327
+ }
1328
+ }
1329
+
1330
+ #ifdef IS_REANIMATED_EXAMPLE_APP
1331
+
1332
+ std::string format(bool b) {
1333
+ return b ? "✅" : "❌";
1334
+ }
1335
+
1336
+ std::function<std::string()> ReanimatedModuleProxy::createRegistriesLeakCheck() {
1337
+ return [weakThis = weak_from_this()]() {
1338
+ auto strongThis = weakThis.lock();
1339
+ if (!strongThis) {
1340
+ return std::string("");
1341
+ }
1342
+
1343
+ std::string result = "";
1344
+
1345
+ result += "AnimatedPropsRegistry: " + format(strongThis->animatedPropsRegistry_->isEmpty());
1346
+ result += "\nCSSAnimationsRegistry: " + format(strongThis->cssAnimationsRegistry_->isEmpty());
1347
+ result += "\nCSSTransitionsRegistry: " + format(strongThis->cssTransitionsRegistry_->isEmpty());
1348
+ result += "\nStaticPropsRegistry: " + format(strongThis->staticPropsRegistry_->isEmpty()) + "\n";
1349
+
1350
+ return result;
1351
+ };
1352
+ }
1353
+
1354
+ #endif // IS_REANIMATED_EXAMPLE_APP
1355
+
1356
+ jsi::Value ReanimatedModuleProxy::subscribeForKeyboardEvents(
1357
+ jsi::Runtime &rt,
1358
+ const jsi::Value &handlerWorklet,
1359
+ const jsi::Value &isStatusBarTranslucent,
1360
+ const jsi::Value &isNavigationBarTranslucent) {
1361
+ auto serializableHandler = extractSerializableOrThrow<SerializableWorklet>(
1362
+ rt, handlerWorklet, "[Reanimated] Keyboard event handler must be a worklet.");
1363
+ return subscribeForKeyboardEventsFunction_(
1364
+ [=, weakThis = weak_from_this()](int keyboardState, int height) {
1365
+ auto strongThis = weakThis.lock();
1366
+ if (!strongThis) {
1367
+ return;
1368
+ }
1369
+ strongThis->workletsModuleProxy_->getUIWorkletRuntime()->runSync(
1370
+ serializableHandler, jsi::Value(keyboardState), jsi::Value(height));
1371
+ },
1372
+ isStatusBarTranslucent.getBool(),
1373
+ isNavigationBarTranslucent.getBool());
1374
+ }
1375
+
1376
+ void ReanimatedModuleProxy::unsubscribeFromKeyboardEvents(jsi::Runtime &, const jsi::Value &listenerId) {
1377
+ unsubscribeFromKeyboardEventsFunction_(listenerId.asNumber());
1378
+ }
1379
+
1380
+ } // namespace reanimated