@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.
- package/compatibility.json +161 -161
- package/harmony/reanimated/BuildProfile.ets +16 -16
- package/harmony/reanimated/build-profile.json5 +18 -18
- package/harmony/reanimated/hvigorfile.ts +4 -4
- package/harmony/reanimated/index.ets +4 -4
- package/harmony/reanimated/oh-package-lock.json5 +39 -0
- package/harmony/reanimated/oh-package.json5 +12 -12
- package/harmony/reanimated/src/main/cpp/CMakeLists.txt +65 -62
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/AnimatedSensor/AnimatedSensorModule.cpp +81 -81
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/AnimatedSensor/AnimatedSensorModule.h +46 -46
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/InterpolatorRegistry.cpp +390 -390
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/InterpolatorRegistry.h +16 -16
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/definitions.h +30 -30
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/filters/FilterOp.cpp +46 -46
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/filters/FilterOp.h +23 -23
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/Quaternion.cpp +53 -53
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/Quaternion.h +21 -21
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/TransformMatrix.cpp +166 -166
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/TransformMatrix.h +71 -71
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/TransformMatrix2D.cpp +368 -368
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/TransformMatrix2D.h +53 -53
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/TransformMatrix3D.cpp +594 -594
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/TransformMatrix3D.h +67 -67
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/TransformOp.cpp +52 -52
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/TransformOp.h +26 -26
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/vectors.cpp +156 -156
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/transforms/vectors.h +76 -76
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSAngle.cpp +94 -93
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSAngle.h +33 -33
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSBoolean.cpp +48 -48
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSBoolean.h +31 -31
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSColor.cpp +135 -135
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSColor.h +61 -61
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSDiscreteArray.cpp +100 -100
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSDiscreteArray.h +45 -44
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSKeyword.cpp +81 -81
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSKeyword.h +53 -53
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSLength.cpp +122 -122
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSLength.h +38 -38
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSNumber.cpp +82 -82
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSNumber.h +63 -63
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSValue.h +118 -118
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSValueVariant.cpp +174 -174
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSValueVariant.h +111 -111
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/complex/CSSBoxShadow.cpp +196 -196
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/complex/CSSBoxShadow.h +66 -66
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/complex/CSSDropShadow.cpp +134 -134
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/complex/CSSDropShadow.h +44 -44
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/CSSAnimationConfig.cpp +174 -174
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/CSSAnimationConfig.h +49 -49
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/CSSKeyframesConfig.cpp +45 -45
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/CSSKeyframesConfig.h +26 -26
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/CSSTransitionConfig.cpp +90 -90
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/CSSTransitionConfig.h +43 -43
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/common.cpp +17 -17
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/common.h +13 -13
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/CSSAnimation.cpp +127 -127
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/CSSAnimation.h +51 -51
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/CSSTransition.cpp +145 -145
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/CSSTransition.h +47 -47
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/easing/EasingFunctions.cpp +69 -69
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/easing/EasingFunctions.h +22 -22
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/easing/cubicBezier.cpp +66 -66
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/easing/cubicBezier.h +15 -15
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/easing/linear.cpp +28 -28
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/easing/linear.h +15 -15
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/easing/steps.cpp +13 -13
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/easing/steps.h +12 -12
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/InterpolatorFactory.cpp +157 -157
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/InterpolatorFactory.h +189 -189
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/PropertyInterpolator.cpp +76 -76
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/PropertyInterpolator.h +66 -66
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/configs.h +20 -20
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/FilterOperation.cpp +136 -136
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/FilterOperation.h +40 -40
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/FilterOperationInterpolator.cpp +38 -38
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/FilterOperationInterpolator.h +24 -24
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/FilterStyleInterpolator.cpp +58 -58
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/FilterStyleInterpolator.h +24 -24
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/blur.h +14 -14
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/brightness.h +14 -14
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/contrast.h +14 -14
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/dropShadow.h +17 -17
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/grayscale.h +14 -14
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/hueRotate.h +14 -14
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/invert.h +14 -14
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/opacity.h +14 -14
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/saturate.h +14 -14
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/operations/sepia.h +14 -14
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/groups/ArrayPropertiesInterpolator.cpp +95 -95
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/groups/ArrayPropertiesInterpolator.h +36 -36
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/groups/GroupPropertiesInterpolator.cpp +41 -41
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/groups/GroupPropertiesInterpolator.h +32 -32
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/groups/RecordPropertiesInterpolator.cpp +99 -99
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/groups/RecordPropertiesInterpolator.h +37 -37
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/operations/OperationsStyleInterpolator.cpp +308 -308
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/operations/OperationsStyleInterpolator.h +100 -100
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/operations/StyleOperation.cpp +19 -19
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/operations/StyleOperation.h +94 -94
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/operations/StyleOperationInterpolator.cpp +18 -18
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/operations/StyleOperationInterpolator.h +43 -43
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/styles/AnimationStyleInterpolator.h +26 -26
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/styles/TransitionStyleInterpolator.cpp +103 -103
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/styles/TransitionStyleInterpolator.h +42 -42
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/TransformOperation.cpp +224 -224
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/TransformOperation.h +52 -52
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/TransformOperationInterpolator.cpp +218 -218
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/TransformOperationInterpolator.h +89 -89
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/TransformsStyleInterpolator.cpp +149 -149
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/TransformsStyleInterpolator.h +33 -33
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/matrix.cpp +208 -208
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/matrix.h +56 -56
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/perspective.cpp +42 -42
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/perspective.h +20 -20
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/rotate.cpp +41 -41
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/rotate.h +39 -39
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/scale.cpp +28 -28
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/scale.h +25 -25
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/skew.cpp +14 -14
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/skew.h +20 -20
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/translate.cpp +39 -39
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/translate.h +25 -25
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/values/ResolvableValueInterpolator.cpp +47 -47
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/values/ResolvableValueInterpolator.h +43 -43
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/values/SimpleValueInterpolator.cpp +70 -70
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/values/SimpleValueInterpolator.h +40 -40
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/values/ValueInterpolator.cpp +146 -146
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/values/ValueInterpolator.h +71 -71
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/misc/ViewStylesRepository.cpp +155 -155
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/misc/ViewStylesRepository.h +53 -53
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/AnimationProgressProvider.cpp +170 -170
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/AnimationProgressProvider.h +67 -67
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/KeyframeProgressProvider.h +12 -12
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/RawProgressProvider.cpp +41 -41
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/RawProgressProvider.h +31 -31
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/TransitionProgressProvider.cpp +193 -193
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/TransitionProgressProvider.h +77 -77
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/CSSAnimationsRegistry.cpp +340 -340
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/CSSAnimationsRegistry.h +80 -80
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/CSSKeyframesRegistry.cpp +45 -45
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/CSSKeyframesRegistry.h +29 -29
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/CSSTransitionsRegistry.cpp +167 -167
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/CSSTransitionsRegistry.h +51 -51
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/StaticPropsRegistry.cpp +61 -61
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/StaticPropsRegistry.h +33 -33
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGBrush.cpp +80 -80
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGBrush.h +39 -39
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGLength.cpp +93 -93
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGLength.h +36 -36
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGStrokeDashArray.cpp +111 -110
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGStrokeDashArray.h +33 -33
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/DelayedItemsManager.cpp +75 -75
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/DelayedItemsManager.h +45 -45
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/algorithms.cpp +12 -12
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/algorithms.h +10 -10
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/interpolators.cpp +36 -36
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/interpolators.h +23 -23
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/props.cpp +149 -149
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/props.h +32 -32
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.cpp +113 -113
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.h +49 -49
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedCommitShadowNode.h +46 -46
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedMountHook.cpp +56 -56
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedMountHook.h +37 -37
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ShadowTreeCloner.cpp +104 -104
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ShadowTreeCloner.h +22 -22
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.cpp +72 -72
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.h +25 -25
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.cpp +160 -160
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.h +71 -71
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.cpp +161 -161
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.h +65 -65
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationType.h +11 -11
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsManager.cpp +137 -137
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsManager.h +82 -82
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.cpp +79 -79
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.h +81 -81
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp +864 -864
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h +214 -214
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.cpp +897 -897
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.h +220 -220
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.cpp +31 -31
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.h +146 -146
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/PropsDiffer.cpp +456 -456
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/PropsDiffer.h +102 -102
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/SharedTransitions.cpp +544 -544
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/PropValueProcessor.cpp +119 -119
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/PropValueProcessor.h +39 -39
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +1380 -1376
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +230 -228
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.cpp +183 -183
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.h +93 -93
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.cpp +54 -54
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.h +28 -28
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.cpp +58 -58
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.h +31 -31
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/FeatureFlags.cpp +18 -18
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/FeatureFlags.h +44 -44
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/PlatformDepMethodsHolder.h +67 -67
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/ReanimatedSystraceSection.h +114 -114
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/ReanimatedVersion.cpp +46 -46
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/ReanimatedVersion.h +18 -18
- package/harmony/reanimated/src/main/cpp/ReanimatedModule.cpp +233 -230
- package/harmony/reanimated/src/main/cpp/ReanimatedModule.h +23 -23
- package/harmony/reanimated/src/main/cpp/ReanimatedNodesManager.cpp +56 -56
- package/harmony/reanimated/src/main/cpp/ReanimatedNodesManager.h +30 -30
- package/harmony/reanimated/src/main/cpp/ReanimatedPackage.cpp +44 -44
- package/harmony/reanimated/src/main/cpp/ReanimatedPackage.h +16 -16
- package/harmony/reanimated/src/main/cpp/ReanimatedSensor.cpp +265 -265
- package/harmony/reanimated/src/main/cpp/ReanimatedSensor.h +36 -36
- package/harmony/reanimated/src/main/cpp/ReanimatedSensorContainer.cpp +35 -35
- package/harmony/reanimated/src/main/cpp/ReanimatedSensorContainer.h +23 -23
- package/harmony/reanimated/src/main/cpp/ReanimatedUIScheduler.cpp +23 -23
- package/harmony/reanimated/src/main/cpp/ReanimatedUIScheduler.h +19 -19
- package/harmony/reanimated/src/main/cpp/TransformParser.h +93 -93
- package/harmony/reanimated/src/main/ets/AnimationManager.ts +60 -60
- package/harmony/reanimated/src/main/ets/ReanimatedModule.ts +51 -51
- package/harmony/reanimated/src/main/ets/ReanimatedPackage.ts +25 -25
- package/harmony/reanimated/src/main/module.json5 +12 -12
- package/harmony/reanimated/src/main/resources/base/element/color.json +7 -7
- package/harmony/reanimated/src/main/resources/base/element/string.json +15 -15
- package/harmony/reanimated/src/main/resources/base/profile/main_pages.json +5 -5
- package/harmony/reanimated/src/main/resources/en_US/element/string.json +15 -15
- package/harmony/reanimated/src/main/resources/zh_CN/element/string.json +15 -15
- package/harmony/reanimated/ts.ts +6 -6
- package/harmony/reanimated.har +0 -0
- package/package.json +70 -68
- package/scripts/deploy.js +191 -191
- package/scripts/set-reanimated-version.js +37 -37
- package/scripts/update-version.js +119 -119
- package/scripts/validate-react-native-version.js +46 -46
- package/scripts/validate-worklets-build.js +17 -17
- package/scripts/validate-worklets-version.js +84 -79
- package/scripts/worklets-version.json +4 -4
- package/src/index.ts +9 -9
|
@@ -1,864 +1,864 @@
|
|
|
1
|
-
#include <glog/logging.h>
|
|
2
|
-
#include <react/renderer/animations/utils.h>
|
|
3
|
-
#include <react/renderer/core/ConcreteState.h>
|
|
4
|
-
#include <react/renderer/mounting/ShadowViewMutation.h>
|
|
5
|
-
#include <reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h>
|
|
6
|
-
#include <reanimated/LayoutAnimations/PropsDiffer.h>
|
|
7
|
-
#include <reanimated/NativeModules/ReanimatedModuleProxy.h>
|
|
8
|
-
#include <reanimated/Tools/ReanimatedSystraceSection.h>
|
|
9
|
-
|
|
10
|
-
#include <algorithm>
|
|
11
|
-
#include <memory>
|
|
12
|
-
#include <ranges>
|
|
13
|
-
#include <string>
|
|
14
|
-
#include <unordered_set>
|
|
15
|
-
#include <utility>
|
|
16
|
-
#include <vector>
|
|
17
|
-
|
|
18
|
-
namespace reanimated {
|
|
19
|
-
using enum LayoutAnimationType;
|
|
20
|
-
using enum ExitingState;
|
|
21
|
-
|
|
22
|
-
// MARK: MountingOverrideDelegate
|
|
23
|
-
|
|
24
|
-
std::optional<MountingTransaction> LayoutAnimationsProxy_Experimental::pullTransaction(
|
|
25
|
-
SurfaceId surfaceId,
|
|
26
|
-
MountingTransaction::Number transactionNumber,
|
|
27
|
-
const TransactionTelemetry &telemetry,
|
|
28
|
-
ShadowViewMutationList mutations) const {
|
|
29
|
-
ReanimatedSystraceSection d("pullTransaction");
|
|
30
|
-
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
31
|
-
const PropsParserContext propsParserContext{surfaceId, *contextContainer_};
|
|
32
|
-
ShadowViewMutationList filteredMutations;
|
|
33
|
-
auto rootChildCount = static_cast<int>(lightNodes_[surfaceId]->children.size());
|
|
34
|
-
const std::vector<std::shared_ptr<MutationNode>> roots;
|
|
35
|
-
const bool isInTransition = transitionState_;
|
|
36
|
-
|
|
37
|
-
if (isInTransition) {
|
|
38
|
-
updateLightTree(propsParserContext, mutations, filteredMutations);
|
|
39
|
-
handleProgressTransition(filteredMutations, mutations, propsParserContext, surfaceId);
|
|
40
|
-
} else if (!synchronized_) {
|
|
41
|
-
auto actualTop = topScreen[surfaceId];
|
|
42
|
-
updateLightTree(propsParserContext, mutations, filteredMutations);
|
|
43
|
-
auto reactTop = findTopScreen(lightNodes_[surfaceId]);
|
|
44
|
-
if (reactTop == actualTop) {
|
|
45
|
-
synchronized_ = true;
|
|
46
|
-
}
|
|
47
|
-
} else if (!mutations.empty()) {
|
|
48
|
-
auto root = lightNodes_[surfaceId];
|
|
49
|
-
react_native_assert(root && "Root node not found");
|
|
50
|
-
auto beforeTopScreen = topScreen[surfaceId];
|
|
51
|
-
if (beforeTopScreen) {
|
|
52
|
-
ReanimatedSystraceSection s("find before elements");
|
|
53
|
-
findSharedElementsOnScreen(beforeTopScreen, BEFORE, propsParserContext);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
updateLightTree(propsParserContext, mutations, filteredMutations);
|
|
57
|
-
|
|
58
|
-
auto afterTopScreen = findTopScreen(root);
|
|
59
|
-
topScreen[surfaceId] = afterTopScreen;
|
|
60
|
-
if (afterTopScreen) {
|
|
61
|
-
ReanimatedSystraceSection s("find after elements");
|
|
62
|
-
findSharedElementsOnScreen(afterTopScreen, AFTER, propsParserContext);
|
|
63
|
-
#ifdef __APPLE__
|
|
64
|
-
forceScreenSnapshot_(afterTopScreen->current.tag);
|
|
65
|
-
#endif
|
|
66
|
-
}
|
|
67
|
-
const bool hasScreenChanged = beforeTopScreen && afterTopScreen && beforeTopScreen != afterTopScreen;
|
|
68
|
-
|
|
69
|
-
if (hasScreenChanged) {
|
|
70
|
-
// We want to add mutations to hide the views that will start their transitions.
|
|
71
|
-
// To keep things simple, we put mutations related to source views before all muatations
|
|
72
|
-
// and mutations to hide target views after all mutations.
|
|
73
|
-
std::vector<ShadowViewMutation> mergedMutations;
|
|
74
|
-
hideTransitioningViews(BEFORE, mergedMutations, propsParserContext);
|
|
75
|
-
mergedMutations.insert(mergedMutations.end(), filteredMutations.begin(), filteredMutations.end());
|
|
76
|
-
hideTransitioningViews(AFTER, mergedMutations, propsParserContext);
|
|
77
|
-
std::swap(filteredMutations, mergedMutations);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
handleSharedTransitionsStart(
|
|
81
|
-
afterTopScreen, beforeTopScreen, filteredMutations, mutations, propsParserContext, surfaceId);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
for (auto &node : entering_) {
|
|
85
|
-
startEnteringAnimation(node);
|
|
86
|
-
}
|
|
87
|
-
for (auto &node : layout_) {
|
|
88
|
-
startLayoutAnimation(node);
|
|
89
|
-
}
|
|
90
|
-
entering_.clear();
|
|
91
|
-
layout_.clear();
|
|
92
|
-
|
|
93
|
-
handleRemovals(filteredMutations, exiting_);
|
|
94
|
-
exiting_.clear();
|
|
95
|
-
|
|
96
|
-
addOngoingAnimations(surfaceId, filteredMutations);
|
|
97
|
-
|
|
98
|
-
cleanupAnimations(filteredMutations, propsParserContext, surfaceId);
|
|
99
|
-
|
|
100
|
-
transitionMap_.clear();
|
|
101
|
-
transitions_.clear();
|
|
102
|
-
|
|
103
|
-
insertContainers(filteredMutations, rootChildCount, surfaceId);
|
|
104
|
-
|
|
105
|
-
return MountingTransaction{surfaceId, transactionNumber, std::move(filteredMutations), telemetry};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
bool LayoutAnimationsProxy_Experimental::shouldOverridePullTransaction() const {
|
|
109
|
-
// we need to listen to every possible mutation to keep the light tree updated
|
|
110
|
-
return true;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// MARK: Light Tree
|
|
114
|
-
|
|
115
|
-
void LayoutAnimationsProxy_Experimental::updateLightTree(
|
|
116
|
-
const PropsParserContext &propsParserContext,
|
|
117
|
-
const ShadowViewMutationList &mutations,
|
|
118
|
-
ShadowViewMutationList &filteredMutations) const {
|
|
119
|
-
ReanimatedSystraceSection s("updateLightTree");
|
|
120
|
-
std::unordered_set<Tag> inserted, moved, deleted;
|
|
121
|
-
for (auto it = mutations.rbegin(); it != mutations.rend(); it++) {
|
|
122
|
-
const auto &mutation = *it;
|
|
123
|
-
switch (mutation.type) {
|
|
124
|
-
case ShadowViewMutation::Delete: {
|
|
125
|
-
deleted.insert(mutation.oldChildShadowView.tag);
|
|
126
|
-
break;
|
|
127
|
-
}
|
|
128
|
-
case ShadowViewMutation::Insert: {
|
|
129
|
-
inserted.insert(mutation.newChildShadowView.tag);
|
|
130
|
-
break;
|
|
131
|
-
}
|
|
132
|
-
case ShadowViewMutation::Remove: {
|
|
133
|
-
const auto tag = mutation.oldChildShadowView.tag;
|
|
134
|
-
if (inserted.contains(tag)) {
|
|
135
|
-
moved.insert(tag);
|
|
136
|
-
}
|
|
137
|
-
break;
|
|
138
|
-
}
|
|
139
|
-
default: {
|
|
140
|
-
// Skip other mutation types. We are only interested in moves and deletions here.
|
|
141
|
-
break;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
for (const auto &mutation : mutations) {
|
|
147
|
-
maybeUpdateWindowDimensions(mutation);
|
|
148
|
-
switch (mutation.type) {
|
|
149
|
-
case ShadowViewMutation::Update: {
|
|
150
|
-
auto &node = lightNodes_[mutation.newChildShadowView.tag];
|
|
151
|
-
react_native_assert(node && "LightNode not found");
|
|
152
|
-
node->previous = mutation.oldChildShadowView;
|
|
153
|
-
#ifdef ANDROID
|
|
154
|
-
// TODO (future): We don't merge the root view as the currently stored version might not be accurate, because of the inconsequential initialization order of proxy and the surface
|
|
155
|
-
if (!isRoot(node) && node->current.props) {
|
|
156
|
-
// On android rawProps are used to store the diffed props so we need to merge them
|
|
157
|
-
// This should soon be replaced in RN with Props 2.0 (the diffing will be done at the end of the pipeline)
|
|
158
|
-
auto ¤tRawProps = node->current.props->rawProps;
|
|
159
|
-
auto mergedRawProps = folly::dynamic::merge(currentRawProps, mutation.newChildShadowView.props->rawProps);
|
|
160
|
-
node->current = mutation.newChildShadowView;
|
|
161
|
-
node->current.props =
|
|
162
|
-
getComponentDescriptorForShadowView(node->current)
|
|
163
|
-
.cloneProps(propsParserContext, mutation.newChildShadowView.props, RawProps(mergedRawProps));
|
|
164
|
-
} else {
|
|
165
|
-
node->current = mutation.newChildShadowView;
|
|
166
|
-
}
|
|
167
|
-
#else
|
|
168
|
-
node->current = mutation.newChildShadowView;
|
|
169
|
-
#endif // ANDROID
|
|
170
|
-
auto tag = mutation.newChildShadowView.tag;
|
|
171
|
-
if (layoutAnimationsManager_->hasLayoutAnimation(tag, LAYOUT)) {
|
|
172
|
-
layout_.push_back(node);
|
|
173
|
-
} else {
|
|
174
|
-
filteredMutations.push_back(mutation);
|
|
175
|
-
}
|
|
176
|
-
break;
|
|
177
|
-
}
|
|
178
|
-
case ShadowViewMutation::Create: {
|
|
179
|
-
const auto &node = std::make_shared<LightNode>();
|
|
180
|
-
node->current = mutation.newChildShadowView;
|
|
181
|
-
react_native_assert(!lightNodes_.contains(mutation.newChildShadowView.tag) && "LightNode already exists");
|
|
182
|
-
|
|
183
|
-
lightNodes_[mutation.newChildShadowView.tag] = node;
|
|
184
|
-
filteredMutations.push_back(mutation);
|
|
185
|
-
break;
|
|
186
|
-
}
|
|
187
|
-
case ShadowViewMutation::Delete: {
|
|
188
|
-
lightNodes_.erase(mutation.oldChildShadowView.tag);
|
|
189
|
-
break;
|
|
190
|
-
}
|
|
191
|
-
case ShadowViewMutation::Insert: {
|
|
192
|
-
transferConfigFromNativeID(mutation.newChildShadowView.props->nativeId, mutation.newChildShadowView.tag);
|
|
193
|
-
auto &node = lightNodes_[mutation.newChildShadowView.tag];
|
|
194
|
-
auto &parent = lightNodes_[mutation.parentTag];
|
|
195
|
-
parent->children.insert(parent->children.begin() + mutation.index, node);
|
|
196
|
-
node->parent = parent;
|
|
197
|
-
const auto tag = mutation.newChildShadowView.tag;
|
|
198
|
-
if (moved.contains(tag) && layoutAnimationsManager_->hasLayoutAnimation(tag, LAYOUT)) {
|
|
199
|
-
filteredMutations.push_back(
|
|
200
|
-
ShadowViewMutation::InsertMutation(mutation.parentTag, node->previous, mutation.index));
|
|
201
|
-
} else if (layoutAnimationsManager_->hasLayoutAnimation(tag, ENTERING)) {
|
|
202
|
-
entering_.push_back(node);
|
|
203
|
-
filteredMutations.push_back(mutation);
|
|
204
|
-
} else {
|
|
205
|
-
filteredMutations.push_back(mutation);
|
|
206
|
-
}
|
|
207
|
-
break;
|
|
208
|
-
}
|
|
209
|
-
case ShadowViewMutation::Remove: {
|
|
210
|
-
const auto &node = lightNodes_[mutation.oldChildShadowView.tag];
|
|
211
|
-
const auto tag = node->current.tag;
|
|
212
|
-
const auto parentTag = mutation.parentTag;
|
|
213
|
-
const auto &parent = lightNodes_[parentTag];
|
|
214
|
-
react_native_assert(
|
|
215
|
-
parent->children[mutation.index]->current.tag == mutation.oldChildShadowView.tag &&
|
|
216
|
-
"Indicies are wrong in Remove mutation");
|
|
217
|
-
|
|
218
|
-
if (deleted.contains(tag) && !deleted.contains(parentTag)) {
|
|
219
|
-
exiting_.push_back(node);
|
|
220
|
-
filteredMutations.push_back(mutation);
|
|
221
|
-
parent->children.erase(parent->children.begin() + mutation.index);
|
|
222
|
-
} else if (!deleted.contains(tag)) {
|
|
223
|
-
filteredMutations.push_back(mutation);
|
|
224
|
-
parent->children.erase(parent->children.begin() + mutation.index);
|
|
225
|
-
}
|
|
226
|
-
break;
|
|
227
|
-
}
|
|
228
|
-
default: {
|
|
229
|
-
react_native_assert(false && "Unsupported mutation type");
|
|
230
|
-
break;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// MARK: Layout Animation Updates
|
|
237
|
-
|
|
238
|
-
std::optional<SurfaceId> LayoutAnimationsProxy_Experimental::progressLayoutAnimation(
|
|
239
|
-
int tag,
|
|
240
|
-
const jsi::Object &newStyle) {
|
|
241
|
-
ReanimatedSystraceSection s("progressLayoutAnimation");
|
|
242
|
-
const auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
243
|
-
const auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
244
|
-
|
|
245
|
-
if (layoutAnimationIt == layoutAnimations_.end()) {
|
|
246
|
-
return {};
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
auto &layoutAnimation = layoutAnimationIt->second;
|
|
250
|
-
|
|
251
|
-
maybeRestoreOpacity(layoutAnimation, newStyle);
|
|
252
|
-
|
|
253
|
-
auto rawProps = std::make_shared<RawProps>(uiRuntime_, jsi::Value(uiRuntime_, newStyle));
|
|
254
|
-
|
|
255
|
-
const PropsParserContext propsParserContext{layoutAnimation.finalView.surfaceId, *contextContainer_};
|
|
256
|
-
#ifdef RN_SERIALIZABLE_STATE
|
|
257
|
-
rawProps = std::make_shared<RawProps>(
|
|
258
|
-
folly::dynamic::merge(layoutAnimation.finalView.props->rawProps, (folly::dynamic)*rawProps));
|
|
259
|
-
#endif
|
|
260
|
-
auto newProps = getComponentDescriptorForShadowView(layoutAnimation.finalView)
|
|
261
|
-
.cloneProps(propsParserContext, layoutAnimation.finalView.props, std::move(*rawProps));
|
|
262
|
-
auto &updateMap = surfaceManager.getUpdateMap(layoutAnimation.finalView.surfaceId);
|
|
263
|
-
updateMap.insert_or_assign(tag, UpdateValues{newProps, Frame(uiRuntime_, newStyle)});
|
|
264
|
-
|
|
265
|
-
return layoutAnimation.finalView.surfaceId;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
std::optional<SurfaceId> LayoutAnimationsProxy_Experimental::endLayoutAnimation(int tag, bool shouldRemove) {
|
|
269
|
-
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
270
|
-
auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
271
|
-
|
|
272
|
-
if (layoutAnimationIt == layoutAnimations_.end()) {
|
|
273
|
-
return {};
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
auto &layoutAnimation = layoutAnimationIt->second;
|
|
277
|
-
|
|
278
|
-
// multiple layout animations can be triggered for a view
|
|
279
|
-
// one after the other, so we need to keep count of how many
|
|
280
|
-
// were actually triggered, so that we don't cleanup necessary
|
|
281
|
-
// structures too early
|
|
282
|
-
if (layoutAnimation.count > 1) {
|
|
283
|
-
layoutAnimation.count--;
|
|
284
|
-
return {};
|
|
285
|
-
}
|
|
286
|
-
finishedAnimationTags_.push_back(tag);
|
|
287
|
-
auto surfaceId = layoutAnimation.finalView.surfaceId;
|
|
288
|
-
|
|
289
|
-
if (sharedTransitionManager_->tagToName_.contains(tag)) {
|
|
290
|
-
auto sharedTag = sharedTransitionManager_->tagToName_[tag];
|
|
291
|
-
sharedTransitionManager_->containerTags_.erase(sharedTag);
|
|
292
|
-
|
|
293
|
-
sharedContainersToRemove_.push_back(tag);
|
|
294
|
-
tagsToRestore_.push_back(restoreMap_[tag][1]);
|
|
295
|
-
transformForNode_.clear();
|
|
296
|
-
}
|
|
297
|
-
if (!shouldRemove) {
|
|
298
|
-
return surfaceId;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
auto node = lightNodes_[tag];
|
|
302
|
-
react_native_assert(node && "LightNode not found");
|
|
303
|
-
|
|
304
|
-
node->state = DEAD;
|
|
305
|
-
lightNodes_.erase(tag);
|
|
306
|
-
deadNodes.insert(node);
|
|
307
|
-
|
|
308
|
-
return surfaceId;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
void LayoutAnimationsProxy_Experimental::handleRemovals(
|
|
312
|
-
ShadowViewMutationList &filteredMutations,
|
|
313
|
-
std::vector<std::shared_ptr<LightNode>> &roots) const {
|
|
314
|
-
ReanimatedSystraceSection s("handleRemovals");
|
|
315
|
-
// iterate from the end, so that children
|
|
316
|
-
// with higher indices appear first in the mutations list
|
|
317
|
-
for (auto it = roots.rbegin(); it != roots.rend(); it++) {
|
|
318
|
-
auto &node = *it;
|
|
319
|
-
|
|
320
|
-
const StartAnimationsRecursivelyConfig config = {
|
|
321
|
-
.shouldRemoveSubviewsWithoutAnimations = true,
|
|
322
|
-
.shouldAnimate = true,
|
|
323
|
-
.isScreenPop = false,
|
|
324
|
-
};
|
|
325
|
-
|
|
326
|
-
if (startAnimationsRecursively(node, filteredMutations, config)) {
|
|
327
|
-
auto parent = node->parent.lock();
|
|
328
|
-
react_native_assert(parent && "Parent node is nullptr");
|
|
329
|
-
// TODO (future): figure out a better way to handle this
|
|
330
|
-
// Currently we remove each view, and then if we want to animate it, reinsert it at the end.
|
|
331
|
-
// This is nice, but introduces extra mutations (which could have some side effects, like making a snapshot in RNScreens),
|
|
332
|
-
// and it changes the zIndex of animated views, which is different from what've had.
|
|
333
|
-
// The biggest convenience of this approach is that it is much easier to maintain indices of animated views, and handle reparentings.
|
|
334
|
-
|
|
335
|
-
auto current = node->current;
|
|
336
|
-
if (layoutAnimations_.contains(node->current.tag)) {
|
|
337
|
-
current = layoutAnimations_.at(node->current.tag).currentView;
|
|
338
|
-
}
|
|
339
|
-
filteredMutations.push_back(
|
|
340
|
-
ShadowViewMutation::InsertMutation(parent->current.tag, current, static_cast<int>(parent->children.size())));
|
|
341
|
-
parent->children.push_back(node);
|
|
342
|
-
if (node->state == UNDEFINED) {
|
|
343
|
-
node->state = WAITING;
|
|
344
|
-
}
|
|
345
|
-
} else {
|
|
346
|
-
maybeCancelAnimation(node->current.tag);
|
|
347
|
-
filteredMutations.push_back(ShadowViewMutation::DeleteMutation(node->current));
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
for (const auto &node : deadNodes) {
|
|
352
|
-
if (node->state != DELETED) {
|
|
353
|
-
auto parent = node->parent.lock();
|
|
354
|
-
react_native_assert(parent && "Parent node is nullptr");
|
|
355
|
-
auto index = parent->removeChild(node);
|
|
356
|
-
react_native_assert(index != -1 && "Dead node not found");
|
|
357
|
-
|
|
358
|
-
endAnimationsRecursively(node, index, filteredMutations);
|
|
359
|
-
maybeDropAncestors(parent, filteredMutations);
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
deadNodes.clear();
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
void LayoutAnimationsProxy_Experimental::addOngoingAnimations(SurfaceId surfaceId, ShadowViewMutationList &mutations)
|
|
366
|
-
const {
|
|
367
|
-
ReanimatedSystraceSection s1("addOngoingAnimations");
|
|
368
|
-
auto &updateMap = surfaceManager.getUpdateMap(surfaceId);
|
|
369
|
-
#ifdef ANDROID
|
|
370
|
-
std::vector<int> tagsToUpdate;
|
|
371
|
-
tagsToUpdate.reserve(updateMap.size());
|
|
372
|
-
for (auto &[tag, updateValues] : updateMap) {
|
|
373
|
-
tagsToUpdate.push_back(tag);
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
auto maybeCorrectedTags = preserveMountedTags_(tagsToUpdate);
|
|
377
|
-
if (!maybeCorrectedTags.has_value()) {
|
|
378
|
-
return;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
auto correctedTags = maybeCorrectedTags->get();
|
|
382
|
-
|
|
383
|
-
// since the map is not updated, we can assume that the ordering of tags in
|
|
384
|
-
// correctedTags matches the iterator
|
|
385
|
-
int i = -1;
|
|
386
|
-
#endif
|
|
387
|
-
for (auto &[tag, updateValues] : updateMap) {
|
|
388
|
-
#ifdef ANDROID
|
|
389
|
-
i++;
|
|
390
|
-
if (correctedTags[i] == -1) {
|
|
391
|
-
// skip views that have not been mounted yet
|
|
392
|
-
// on Android we start entering animations from the JS thread
|
|
393
|
-
// so it might happen, that the first frame of the animation goes through
|
|
394
|
-
// before the view is first mounted
|
|
395
|
-
// https://github.com/software-mansion/react-native-reanimated/issues/7493
|
|
396
|
-
continue;
|
|
397
|
-
}
|
|
398
|
-
#endif
|
|
399
|
-
|
|
400
|
-
const auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
401
|
-
|
|
402
|
-
if (layoutAnimationIt == layoutAnimations_.end()) {
|
|
403
|
-
continue;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
auto &layoutAnimation = layoutAnimationIt->second;
|
|
407
|
-
layoutAnimation.isViewAlreadyMounted = true;
|
|
408
|
-
auto newView = layoutAnimation.finalView;
|
|
409
|
-
if (updateValues.newProps) {
|
|
410
|
-
newView.props = updateValues.newProps;
|
|
411
|
-
}
|
|
412
|
-
updateLayoutMetrics(newView.layoutMetrics, updateValues.frame);
|
|
413
|
-
|
|
414
|
-
mutations.push_back(
|
|
415
|
-
ShadowViewMutation::UpdateMutation(layoutAnimation.currentView, newView, layoutAnimation.parentTag));
|
|
416
|
-
layoutAnimation.currentView = newView;
|
|
417
|
-
}
|
|
418
|
-
updateMap.clear();
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
void LayoutAnimationsProxy_Experimental::endAnimationsRecursively(
|
|
422
|
-
const std::shared_ptr<LightNode> &node,
|
|
423
|
-
int index,
|
|
424
|
-
ShadowViewMutationList &mutations) const {
|
|
425
|
-
maybeCancelAnimation(node->current.tag);
|
|
426
|
-
node->state = DELETED;
|
|
427
|
-
// iterate from the end, so that children
|
|
428
|
-
// with higher indices appear first in the mutations list
|
|
429
|
-
|
|
430
|
-
const int childrenSize = static_cast<int>(node->children.size());
|
|
431
|
-
for (int i = childrenSize - 1; i >= 0; i--) {
|
|
432
|
-
auto &subNode = node->children[i];
|
|
433
|
-
if (subNode->state != DELETED) {
|
|
434
|
-
endAnimationsRecursively(subNode, i, mutations);
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
node->children.clear();
|
|
438
|
-
|
|
439
|
-
const auto &parent = node->parent.lock();
|
|
440
|
-
react_native_assert(parent && "Parent node is nullptr");
|
|
441
|
-
mutations.push_back(ShadowViewMutation::RemoveMutation(parent->current.tag, node->current, index));
|
|
442
|
-
mutations.push_back(ShadowViewMutation::DeleteMutation(node->current));
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
void LayoutAnimationsProxy_Experimental::maybeDropAncestors(
|
|
446
|
-
const std::shared_ptr<LightNode> &node,
|
|
447
|
-
ShadowViewMutationList &cleanupMutations) const {
|
|
448
|
-
if (node->children.size() != 0 || node->state == ANIMATING || node->state == UNDEFINED) {
|
|
449
|
-
return;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
auto parent = node->parent.lock();
|
|
453
|
-
react_native_assert(parent && "Parent node is nullptr");
|
|
454
|
-
auto index = parent->removeChild(node);
|
|
455
|
-
react_native_assert(index != -1 && "Child node not found");
|
|
456
|
-
|
|
457
|
-
node->state = DELETED;
|
|
458
|
-
maybeCancelAnimation(node->current.tag);
|
|
459
|
-
cleanupMutations.push_back(ShadowViewMutation::RemoveMutation(parent->current.tag, node->current, index));
|
|
460
|
-
cleanupMutations.push_back(ShadowViewMutation::DeleteMutation(node->current));
|
|
461
|
-
maybeDropAncestors(parent, cleanupMutations);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
const ComponentDescriptor &LayoutAnimationsProxy_Experimental::getComponentDescriptorForShadowView(
|
|
465
|
-
const ShadowView &shadowView) const {
|
|
466
|
-
return componentDescriptorRegistry_->at(shadowView.componentHandle);
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
bool LayoutAnimationsProxy_Experimental::startAnimationsRecursively(
|
|
470
|
-
const std::shared_ptr<LightNode> &node,
|
|
471
|
-
ShadowViewMutationList &mutations,
|
|
472
|
-
StartAnimationsRecursivelyConfig config) const {
|
|
473
|
-
auto &[shouldRemoveSubviewsWithoutAnimations, shouldAnimate, isScreenPop] = config;
|
|
474
|
-
if (isRNSScreenOrStack(node)) {
|
|
475
|
-
isScreenPop = true;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
shouldAnimate = !isScreenPop && layoutAnimationsManager_->shouldAnimateExiting(node->current.tag, shouldAnimate);
|
|
479
|
-
|
|
480
|
-
const bool hasExitAnimation =
|
|
481
|
-
shouldAnimate && layoutAnimationsManager_->hasLayoutAnimation(node->current.tag, LayoutAnimationType::EXITING);
|
|
482
|
-
bool hasAnimatedChildren = false;
|
|
483
|
-
|
|
484
|
-
shouldRemoveSubviewsWithoutAnimations = shouldRemoveSubviewsWithoutAnimations && !hasExitAnimation;
|
|
485
|
-
std::vector<std::shared_ptr<LightNode>> toBeRemoved;
|
|
486
|
-
|
|
487
|
-
// iterate from the end, so that children
|
|
488
|
-
// with higher indices appear first in the mutations list
|
|
489
|
-
auto index = static_cast<int>(node->children.size());
|
|
490
|
-
for (auto it = node->children.rbegin(); it != node->children.rend(); it++) {
|
|
491
|
-
index--;
|
|
492
|
-
auto &subNode = *it;
|
|
493
|
-
if (subNode->state != UNDEFINED) {
|
|
494
|
-
if (shouldAnimate && subNode->state != DEAD) {
|
|
495
|
-
hasAnimatedChildren = true;
|
|
496
|
-
} else {
|
|
497
|
-
endAnimationsRecursively(subNode, index, mutations);
|
|
498
|
-
toBeRemoved.push_back(subNode);
|
|
499
|
-
}
|
|
500
|
-
} else if (startAnimationsRecursively(subNode, mutations, config)) {
|
|
501
|
-
hasAnimatedChildren = true;
|
|
502
|
-
} else if (shouldRemoveSubviewsWithoutAnimations) {
|
|
503
|
-
maybeCancelAnimation(subNode->current.tag);
|
|
504
|
-
mutations.push_back(ShadowViewMutation::RemoveMutation(node->current.tag, subNode->current, index));
|
|
505
|
-
toBeRemoved.push_back(subNode);
|
|
506
|
-
subNode->state = DELETED;
|
|
507
|
-
mutations.push_back(ShadowViewMutation::DeleteMutation(subNode->current));
|
|
508
|
-
} else {
|
|
509
|
-
subNode->state = WAITING;
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
for (auto &subNode : toBeRemoved) {
|
|
514
|
-
node->removeChild(subNode);
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
const bool wantAnimateExit = hasExitAnimation || hasAnimatedChildren;
|
|
518
|
-
|
|
519
|
-
if (hasExitAnimation) {
|
|
520
|
-
node->state = ANIMATING;
|
|
521
|
-
startExitingAnimation(node);
|
|
522
|
-
lightNodes_[node->current.tag] = node;
|
|
523
|
-
} else {
|
|
524
|
-
// TODO (future): add proper cleanup
|
|
525
|
-
// layoutAnimationsManager_->clearLayoutAnimationConfig(node->tag);
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
return wantAnimateExit;
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
void LayoutAnimationsProxy_Experimental::updateOngoingAnimationTarget(const int tag, const ShadowViewMutation &mutation)
|
|
532
|
-
const {
|
|
533
|
-
layoutAnimations_[tag].finalView = mutation.newChildShadowView;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
void LayoutAnimationsProxy_Experimental::maybeCancelAnimation(const int tag) const {
|
|
537
|
-
if (!layoutAnimations_.contains(tag)) {
|
|
538
|
-
return;
|
|
539
|
-
}
|
|
540
|
-
layoutAnimations_.erase(tag);
|
|
541
|
-
uiScheduler_->scheduleOnUI([weakThis = weak_from_this(), tag]() {
|
|
542
|
-
auto strongThis = weakThis.lock();
|
|
543
|
-
if (!strongThis) {
|
|
544
|
-
return;
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
auto &uiRuntime = strongThis->uiRuntime_;
|
|
548
|
-
strongThis->layoutAnimationsManager_->cancelLayoutAnimation(uiRuntime, tag);
|
|
549
|
-
});
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
void LayoutAnimationsProxy_Experimental::transferConfigFromNativeID(const std::string &nativeIdString, const int tag)
|
|
553
|
-
const {
|
|
554
|
-
if (nativeIdString.empty() || nativeIdString.length() > 9) {
|
|
555
|
-
return;
|
|
556
|
-
}
|
|
557
|
-
auto nativeId = 0;
|
|
558
|
-
for (int i = 0; i < nativeIdString.length(); i++) {
|
|
559
|
-
if (nativeIdString[i] < '0' || nativeIdString[i] > '9') {
|
|
560
|
-
return;
|
|
561
|
-
}
|
|
562
|
-
nativeId *= 10;
|
|
563
|
-
nativeId += nativeIdString[i] - '0';
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
layoutAnimationsManager_->transferConfigFromNativeID(nativeId, tag);
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
// When entering animations start, we temporarily set opacity to 0
|
|
570
|
-
// so that we can immediately insert the view at the right position
|
|
571
|
-
// and schedule the animation on the UI thread
|
|
572
|
-
ShadowView LayoutAnimationsProxy_Experimental::cloneViewWithoutOpacity(
|
|
573
|
-
const ShadowView &shadowView,
|
|
574
|
-
const PropsParserContext &propsParserContext) const {
|
|
575
|
-
auto newView = shadowView;
|
|
576
|
-
const folly::dynamic opacity = folly::dynamic::object("opacity", 0);
|
|
577
|
-
auto newProps =
|
|
578
|
-
getComponentDescriptorForShadowView(newView).cloneProps(propsParserContext, newView.props, RawProps(opacity));
|
|
579
|
-
newView.props = newProps;
|
|
580
|
-
return newView;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
ShadowView LayoutAnimationsProxy_Experimental::cloneViewWithOpacity(
|
|
584
|
-
const ShadowView &shadowView,
|
|
585
|
-
const PropsParserContext &propsParserContext) const {
|
|
586
|
-
auto newView = shadowView;
|
|
587
|
-
const auto &props = static_cast<const ViewProps &>(*newView.props);
|
|
588
|
-
const folly::dynamic opacity = folly::dynamic::object("opacity", props.opacity);
|
|
589
|
-
auto newProps =
|
|
590
|
-
getComponentDescriptorForShadowView(newView).cloneProps(propsParserContext, newView.props, RawProps(opacity));
|
|
591
|
-
newView.props = newProps;
|
|
592
|
-
return newView;
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
void LayoutAnimationsProxy_Experimental::maybeRestoreOpacity(
|
|
596
|
-
reanimated::LayoutAnimation &layoutAnimation,
|
|
597
|
-
const jsi::Object &newStyle) const {
|
|
598
|
-
if (layoutAnimation.opacity && !newStyle.hasProperty(uiRuntime_, "opacity")) {
|
|
599
|
-
newStyle.setProperty(uiRuntime_, "opacity", jsi::Value(*layoutAnimation.opacity));
|
|
600
|
-
if (layoutAnimation.isViewAlreadyMounted) {
|
|
601
|
-
// We want to reset opacity only when we are sure that this update will be
|
|
602
|
-
// applied to the native view. Otherwise, we want to update opacity using
|
|
603
|
-
// the `restoreOpacityInCaseOfFlakyEnteringAnimation` method.
|
|
604
|
-
layoutAnimation.opacity.reset();
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
void LayoutAnimationsProxy_Experimental::maybeUpdateWindowDimensions(
|
|
610
|
-
const facebook::react::ShadowViewMutation &mutation) const {
|
|
611
|
-
if (mutation.type == ShadowViewMutation::Update &&
|
|
612
|
-
!std::strcmp(mutation.oldChildShadowView.componentName, RootComponentName)) {
|
|
613
|
-
surfaceManager.updateWindow(
|
|
614
|
-
mutation.newChildShadowView.tag,
|
|
615
|
-
mutation.newChildShadowView.layoutMetrics.frame.size.width,
|
|
616
|
-
mutation.newChildShadowView.layoutMetrics.frame.size.height);
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
void LayoutAnimationsProxy_Experimental::cleanupAnimations(
|
|
621
|
-
ShadowViewMutationList &filteredMutations,
|
|
622
|
-
const PropsParserContext &propsParserContext,
|
|
623
|
-
SurfaceId surfaceId) const {
|
|
624
|
-
ReanimatedSystraceSection s("cleanupAnimations");
|
|
625
|
-
cleanupSharedTransitions(filteredMutations, propsParserContext, surfaceId);
|
|
626
|
-
|
|
627
|
-
#ifdef ANDROID
|
|
628
|
-
restoreOpacityInCaseOfFlakyEnteringAnimation(surfaceId);
|
|
629
|
-
#endif // ANDROID
|
|
630
|
-
for (const auto tag : finishedAnimationTags_) {
|
|
631
|
-
auto &updateMap = surfaceManager.getUpdateMap(surfaceId);
|
|
632
|
-
layoutAnimations_.erase(tag);
|
|
633
|
-
updateMap.erase(tag);
|
|
634
|
-
}
|
|
635
|
-
finishedAnimationTags_.clear();
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
// MARK: Start Animation
|
|
639
|
-
|
|
640
|
-
ShadowView LayoutAnimationsProxy_Experimental::maybeCreateLayoutAnimation(
|
|
641
|
-
ShadowView &before,
|
|
642
|
-
const ShadowView &after,
|
|
643
|
-
const Tag parentTag) const {
|
|
644
|
-
auto count = 1;
|
|
645
|
-
const auto tag = after.tag;
|
|
646
|
-
auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
647
|
-
auto &oldView = before;
|
|
648
|
-
|
|
649
|
-
if (layoutAnimationIt != layoutAnimations_.end()) {
|
|
650
|
-
auto &layoutAnimation = layoutAnimationIt->second;
|
|
651
|
-
oldView = layoutAnimation.currentView;
|
|
652
|
-
count = layoutAnimation.count + 1;
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
auto finalView = after;
|
|
656
|
-
auto currentView = oldView;
|
|
657
|
-
auto startView = oldView;
|
|
658
|
-
|
|
659
|
-
layoutAnimations_[tag] = {
|
|
660
|
-
.finalView = finalView,
|
|
661
|
-
.currentView = currentView,
|
|
662
|
-
.startView = startView,
|
|
663
|
-
.parentTag = parentTag,
|
|
664
|
-
.count = count,
|
|
665
|
-
};
|
|
666
|
-
|
|
667
|
-
return oldView;
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
void LayoutAnimationsProxy_Experimental::startEnteringAnimation(const std::shared_ptr<LightNode> &node) const {
|
|
671
|
-
auto newChildShadowView = node->current;
|
|
672
|
-
const auto &finalView = newChildShadowView;
|
|
673
|
-
const auto ¤tView = newChildShadowView;
|
|
674
|
-
|
|
675
|
-
const auto &props = newChildShadowView.props;
|
|
676
|
-
auto &viewProps = static_cast<const ViewProps &>(*props);
|
|
677
|
-
const auto opacity = viewProps.opacity;
|
|
678
|
-
const auto &parent = node->parent.lock();
|
|
679
|
-
react_native_assert(parent && "Parent node is nullptr");
|
|
680
|
-
const auto parentTag = parent->current.tag;
|
|
681
|
-
|
|
682
|
-
uiScheduler_->scheduleOnUI(
|
|
683
|
-
[weakThis = weak_from_this(), finalView, currentView, newChildShadowView, parentTag, opacity]() {
|
|
684
|
-
auto strongThis = weakThis.lock();
|
|
685
|
-
if (!strongThis) {
|
|
686
|
-
return;
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
Rect window;
|
|
690
|
-
const auto tag = newChildShadowView.tag;
|
|
691
|
-
{
|
|
692
|
-
auto lock = std::unique_lock<std::recursive_mutex>(strongThis->mutex);
|
|
693
|
-
strongThis->layoutAnimations_[tag] = {
|
|
694
|
-
.finalView = newChildShadowView,
|
|
695
|
-
.currentView = newChildShadowView,
|
|
696
|
-
.startView = newChildShadowView,
|
|
697
|
-
.parentTag = parentTag,
|
|
698
|
-
.opacity = opacity,
|
|
699
|
-
};
|
|
700
|
-
window = strongThis->surfaceManager.getWindow(newChildShadowView.surfaceId);
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
const Snapshot values(newChildShadowView, window);
|
|
704
|
-
auto &uiRuntime = strongThis->uiRuntime_;
|
|
705
|
-
const jsi::Object yogaValues(uiRuntime);
|
|
706
|
-
yogaValues.setProperty(uiRuntime, "targetOriginX", values.x);
|
|
707
|
-
yogaValues.setProperty(uiRuntime, "targetGlobalOriginX", values.x);
|
|
708
|
-
yogaValues.setProperty(uiRuntime, "targetOriginY", values.y);
|
|
709
|
-
yogaValues.setProperty(uiRuntime, "targetGlobalOriginY", values.y);
|
|
710
|
-
yogaValues.setProperty(uiRuntime, "targetWidth", values.width);
|
|
711
|
-
yogaValues.setProperty(uiRuntime, "targetHeight", values.height);
|
|
712
|
-
yogaValues.setProperty(uiRuntime, "windowWidth", values.windowWidth);
|
|
713
|
-
yogaValues.setProperty(uiRuntime, "windowHeight", values.windowHeight);
|
|
714
|
-
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
715
|
-
uiRuntime, tag, LayoutAnimationType::ENTERING, yogaValues);
|
|
716
|
-
});
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
void LayoutAnimationsProxy_Experimental::startExitingAnimation(const std::shared_ptr<LightNode> &node) const {
|
|
720
|
-
auto &oldChildShadowView = node->current;
|
|
721
|
-
const auto surfaceId = oldChildShadowView.surfaceId;
|
|
722
|
-
const auto tag = oldChildShadowView.tag;
|
|
723
|
-
const auto &parent = node->parent.lock();
|
|
724
|
-
react_native_assert(parent && "Parent node is nullptr");
|
|
725
|
-
const auto parentTag = parent->current.tag;
|
|
726
|
-
|
|
727
|
-
uiScheduler_->scheduleOnUI([weakThis = weak_from_this(), tag, parentTag, oldChildShadowView, surfaceId]() {
|
|
728
|
-
auto strongThis = weakThis.lock();
|
|
729
|
-
if (!strongThis) {
|
|
730
|
-
return;
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
auto oldView = oldChildShadowView;
|
|
734
|
-
Rect window{};
|
|
735
|
-
{
|
|
736
|
-
auto &mutex = strongThis->mutex;
|
|
737
|
-
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
738
|
-
oldView = strongThis->maybeCreateLayoutAnimation(oldView, oldView, parentTag);
|
|
739
|
-
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
const Snapshot values(oldView, window);
|
|
743
|
-
|
|
744
|
-
auto &uiRuntime = strongThis->uiRuntime_;
|
|
745
|
-
const jsi::Object yogaValues(uiRuntime);
|
|
746
|
-
yogaValues.setProperty(uiRuntime, "currentOriginX", values.x);
|
|
747
|
-
yogaValues.setProperty(uiRuntime, "currentGlobalOriginX", values.x);
|
|
748
|
-
yogaValues.setProperty(uiRuntime, "currentOriginY", values.y);
|
|
749
|
-
yogaValues.setProperty(uiRuntime, "currentGlobalOriginY", values.y);
|
|
750
|
-
yogaValues.setProperty(uiRuntime, "currentWidth", values.width);
|
|
751
|
-
yogaValues.setProperty(uiRuntime, "currentHeight", values.height);
|
|
752
|
-
yogaValues.setProperty(uiRuntime, "windowWidth", values.windowWidth);
|
|
753
|
-
yogaValues.setProperty(uiRuntime, "windowHeight", values.windowHeight);
|
|
754
|
-
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
755
|
-
uiRuntime, tag, LayoutAnimationType::EXITING, yogaValues);
|
|
756
|
-
strongThis->layoutAnimationsManager_->clearLayoutAnimationConfig(tag);
|
|
757
|
-
});
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
void LayoutAnimationsProxy_Experimental::startLayoutAnimation(const std::shared_ptr<LightNode> &node) const {
|
|
761
|
-
auto oldChildShadowView = node->previous;
|
|
762
|
-
auto newChildShadowView = node->current;
|
|
763
|
-
auto surfaceId = oldChildShadowView.surfaceId;
|
|
764
|
-
const auto tag = oldChildShadowView.tag;
|
|
765
|
-
const auto &parent = node->parent.lock();
|
|
766
|
-
react_native_assert(parent && "Parent node is nullptr");
|
|
767
|
-
const auto parentTag = parent->current.tag;
|
|
768
|
-
|
|
769
|
-
uiScheduler_->scheduleOnUI(
|
|
770
|
-
[weakThis = weak_from_this(), surfaceId, oldChildShadowView, newChildShadowView, parentTag, tag]() {
|
|
771
|
-
auto strongThis = weakThis.lock();
|
|
772
|
-
if (!strongThis) {
|
|
773
|
-
return;
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
auto oldView = oldChildShadowView;
|
|
777
|
-
Rect window{};
|
|
778
|
-
{
|
|
779
|
-
auto &mutex = strongThis->mutex;
|
|
780
|
-
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
781
|
-
oldView = strongThis->maybeCreateLayoutAnimation(oldView, newChildShadowView, parentTag);
|
|
782
|
-
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
const Snapshot currentValues(oldView, window);
|
|
786
|
-
const Snapshot targetValues(newChildShadowView, window);
|
|
787
|
-
|
|
788
|
-
auto &uiRuntime = strongThis->uiRuntime_;
|
|
789
|
-
const jsi::Object yogaValues(uiRuntime);
|
|
790
|
-
yogaValues.setProperty(uiRuntime, "currentOriginX", currentValues.x);
|
|
791
|
-
yogaValues.setProperty(uiRuntime, "currentGlobalOriginX", currentValues.x);
|
|
792
|
-
yogaValues.setProperty(uiRuntime, "currentOriginY", currentValues.y);
|
|
793
|
-
yogaValues.setProperty(uiRuntime, "currentGlobalOriginY", currentValues.y);
|
|
794
|
-
yogaValues.setProperty(uiRuntime, "currentWidth", currentValues.width);
|
|
795
|
-
yogaValues.setProperty(uiRuntime, "currentHeight", currentValues.height);
|
|
796
|
-
yogaValues.setProperty(uiRuntime, "targetOriginX", targetValues.x);
|
|
797
|
-
yogaValues.setProperty(uiRuntime, "targetGlobalOriginX", targetValues.x);
|
|
798
|
-
yogaValues.setProperty(uiRuntime, "targetOriginY", targetValues.y);
|
|
799
|
-
yogaValues.setProperty(uiRuntime, "targetGlobalOriginY", targetValues.y);
|
|
800
|
-
yogaValues.setProperty(uiRuntime, "targetWidth", targetValues.width);
|
|
801
|
-
yogaValues.setProperty(uiRuntime, "targetHeight", targetValues.height);
|
|
802
|
-
yogaValues.setProperty(uiRuntime, "windowWidth", targetValues.windowWidth);
|
|
803
|
-
yogaValues.setProperty(uiRuntime, "windowHeight", targetValues.windowHeight);
|
|
804
|
-
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
805
|
-
uiRuntime, tag, LayoutAnimationType::LAYOUT, yogaValues);
|
|
806
|
-
});
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
void LayoutAnimationsProxy_Experimental::startSharedTransition(
|
|
810
|
-
const int tag,
|
|
811
|
-
const ShadowView &before,
|
|
812
|
-
const ShadowView &after,
|
|
813
|
-
SurfaceId surfaceId) const {
|
|
814
|
-
uiScheduler_->scheduleOnUI([weakThis = weak_from_this(), before, after, surfaceId, tag]() {
|
|
815
|
-
auto strongThis = weakThis.lock();
|
|
816
|
-
if (!strongThis) {
|
|
817
|
-
return;
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
auto oldView = before;
|
|
821
|
-
Rect window{};
|
|
822
|
-
{
|
|
823
|
-
auto &mutex = strongThis->mutex;
|
|
824
|
-
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
825
|
-
oldView = strongThis->maybeCreateLayoutAnimation(oldView, after, surfaceId);
|
|
826
|
-
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
auto &uiRuntime = strongThis->uiRuntime_;
|
|
830
|
-
auto propsDiffer = PropsDiffer(uiRuntime, oldView, after);
|
|
831
|
-
|
|
832
|
-
const auto &propsDiff = propsDiffer.computeDiff(uiRuntime);
|
|
833
|
-
|
|
834
|
-
propsDiff.setProperty(uiRuntime, "windowWidth", window.width);
|
|
835
|
-
propsDiff.setProperty(uiRuntime, "windowHeight", window.height);
|
|
836
|
-
|
|
837
|
-
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
838
|
-
uiRuntime, tag, LayoutAnimationType::SHARED_ELEMENT_TRANSITION, propsDiff);
|
|
839
|
-
});
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
void LayoutAnimationsProxy_Experimental::startProgressTransition(
|
|
843
|
-
const int tag,
|
|
844
|
-
const ShadowView &before,
|
|
845
|
-
const ShadowView &after,
|
|
846
|
-
SurfaceId surfaceId) const {
|
|
847
|
-
uiScheduler_->scheduleOnUI([weakThis = weak_from_this(), before, after, surfaceId]() {
|
|
848
|
-
auto strongThis = weakThis.lock();
|
|
849
|
-
if (!strongThis) {
|
|
850
|
-
return;
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
auto oldView = before;
|
|
854
|
-
Rect window{};
|
|
855
|
-
{
|
|
856
|
-
auto &mutex = strongThis->mutex;
|
|
857
|
-
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
858
|
-
oldView = strongThis->maybeCreateLayoutAnimation(oldView, after, surfaceId);
|
|
859
|
-
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
860
|
-
}
|
|
861
|
-
});
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
} // namespace reanimated
|
|
1
|
+
#include <glog/logging.h>
|
|
2
|
+
#include <react/renderer/animations/utils.h>
|
|
3
|
+
#include <react/renderer/core/ConcreteState.h>
|
|
4
|
+
#include <react/renderer/mounting/ShadowViewMutation.h>
|
|
5
|
+
#include <reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h>
|
|
6
|
+
#include <reanimated/LayoutAnimations/PropsDiffer.h>
|
|
7
|
+
#include <reanimated/NativeModules/ReanimatedModuleProxy.h>
|
|
8
|
+
#include <reanimated/Tools/ReanimatedSystraceSection.h>
|
|
9
|
+
|
|
10
|
+
#include <algorithm>
|
|
11
|
+
#include <memory>
|
|
12
|
+
#include <ranges>
|
|
13
|
+
#include <string>
|
|
14
|
+
#include <unordered_set>
|
|
15
|
+
#include <utility>
|
|
16
|
+
#include <vector>
|
|
17
|
+
|
|
18
|
+
namespace reanimated {
|
|
19
|
+
using enum LayoutAnimationType;
|
|
20
|
+
using enum ExitingState;
|
|
21
|
+
|
|
22
|
+
// MARK: MountingOverrideDelegate
|
|
23
|
+
|
|
24
|
+
std::optional<MountingTransaction> LayoutAnimationsProxy_Experimental::pullTransaction(
|
|
25
|
+
SurfaceId surfaceId,
|
|
26
|
+
MountingTransaction::Number transactionNumber,
|
|
27
|
+
const TransactionTelemetry &telemetry,
|
|
28
|
+
ShadowViewMutationList mutations) const {
|
|
29
|
+
ReanimatedSystraceSection d("pullTransaction");
|
|
30
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
31
|
+
const PropsParserContext propsParserContext{surfaceId, *contextContainer_};
|
|
32
|
+
ShadowViewMutationList filteredMutations;
|
|
33
|
+
auto rootChildCount = static_cast<int>(lightNodes_[surfaceId]->children.size());
|
|
34
|
+
const std::vector<std::shared_ptr<MutationNode>> roots;
|
|
35
|
+
const bool isInTransition = transitionState_;
|
|
36
|
+
|
|
37
|
+
if (isInTransition) {
|
|
38
|
+
updateLightTree(propsParserContext, mutations, filteredMutations);
|
|
39
|
+
handleProgressTransition(filteredMutations, mutations, propsParserContext, surfaceId);
|
|
40
|
+
} else if (!synchronized_) {
|
|
41
|
+
auto actualTop = topScreen[surfaceId];
|
|
42
|
+
updateLightTree(propsParserContext, mutations, filteredMutations);
|
|
43
|
+
auto reactTop = findTopScreen(lightNodes_[surfaceId]);
|
|
44
|
+
if (reactTop == actualTop) {
|
|
45
|
+
synchronized_ = true;
|
|
46
|
+
}
|
|
47
|
+
} else if (!mutations.empty()) {
|
|
48
|
+
auto root = lightNodes_[surfaceId];
|
|
49
|
+
react_native_assert(root && "Root node not found");
|
|
50
|
+
auto beforeTopScreen = topScreen[surfaceId];
|
|
51
|
+
if (beforeTopScreen) {
|
|
52
|
+
ReanimatedSystraceSection s("find before elements");
|
|
53
|
+
findSharedElementsOnScreen(beforeTopScreen, BEFORE, propsParserContext);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
updateLightTree(propsParserContext, mutations, filteredMutations);
|
|
57
|
+
|
|
58
|
+
auto afterTopScreen = findTopScreen(root);
|
|
59
|
+
topScreen[surfaceId] = afterTopScreen;
|
|
60
|
+
if (afterTopScreen) {
|
|
61
|
+
ReanimatedSystraceSection s("find after elements");
|
|
62
|
+
findSharedElementsOnScreen(afterTopScreen, AFTER, propsParserContext);
|
|
63
|
+
#ifdef __APPLE__
|
|
64
|
+
forceScreenSnapshot_(afterTopScreen->current.tag);
|
|
65
|
+
#endif
|
|
66
|
+
}
|
|
67
|
+
const bool hasScreenChanged = beforeTopScreen && afterTopScreen && beforeTopScreen != afterTopScreen;
|
|
68
|
+
|
|
69
|
+
if (hasScreenChanged) {
|
|
70
|
+
// We want to add mutations to hide the views that will start their transitions.
|
|
71
|
+
// To keep things simple, we put mutations related to source views before all muatations
|
|
72
|
+
// and mutations to hide target views after all mutations.
|
|
73
|
+
std::vector<ShadowViewMutation> mergedMutations;
|
|
74
|
+
hideTransitioningViews(BEFORE, mergedMutations, propsParserContext);
|
|
75
|
+
mergedMutations.insert(mergedMutations.end(), filteredMutations.begin(), filteredMutations.end());
|
|
76
|
+
hideTransitioningViews(AFTER, mergedMutations, propsParserContext);
|
|
77
|
+
std::swap(filteredMutations, mergedMutations);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
handleSharedTransitionsStart(
|
|
81
|
+
afterTopScreen, beforeTopScreen, filteredMutations, mutations, propsParserContext, surfaceId);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
for (auto &node : entering_) {
|
|
85
|
+
startEnteringAnimation(node);
|
|
86
|
+
}
|
|
87
|
+
for (auto &node : layout_) {
|
|
88
|
+
startLayoutAnimation(node);
|
|
89
|
+
}
|
|
90
|
+
entering_.clear();
|
|
91
|
+
layout_.clear();
|
|
92
|
+
|
|
93
|
+
handleRemovals(filteredMutations, exiting_);
|
|
94
|
+
exiting_.clear();
|
|
95
|
+
|
|
96
|
+
addOngoingAnimations(surfaceId, filteredMutations);
|
|
97
|
+
|
|
98
|
+
cleanupAnimations(filteredMutations, propsParserContext, surfaceId);
|
|
99
|
+
|
|
100
|
+
transitionMap_.clear();
|
|
101
|
+
transitions_.clear();
|
|
102
|
+
|
|
103
|
+
insertContainers(filteredMutations, rootChildCount, surfaceId);
|
|
104
|
+
|
|
105
|
+
return MountingTransaction{surfaceId, transactionNumber, std::move(filteredMutations), telemetry};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
bool LayoutAnimationsProxy_Experimental::shouldOverridePullTransaction() const {
|
|
109
|
+
// we need to listen to every possible mutation to keep the light tree updated
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// MARK: Light Tree
|
|
114
|
+
|
|
115
|
+
void LayoutAnimationsProxy_Experimental::updateLightTree(
|
|
116
|
+
const PropsParserContext &propsParserContext,
|
|
117
|
+
const ShadowViewMutationList &mutations,
|
|
118
|
+
ShadowViewMutationList &filteredMutations) const {
|
|
119
|
+
ReanimatedSystraceSection s("updateLightTree");
|
|
120
|
+
std::unordered_set<Tag> inserted, moved, deleted;
|
|
121
|
+
for (auto it = mutations.rbegin(); it != mutations.rend(); it++) {
|
|
122
|
+
const auto &mutation = *it;
|
|
123
|
+
switch (mutation.type) {
|
|
124
|
+
case ShadowViewMutation::Delete: {
|
|
125
|
+
deleted.insert(mutation.oldChildShadowView.tag);
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
case ShadowViewMutation::Insert: {
|
|
129
|
+
inserted.insert(mutation.newChildShadowView.tag);
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
case ShadowViewMutation::Remove: {
|
|
133
|
+
const auto tag = mutation.oldChildShadowView.tag;
|
|
134
|
+
if (inserted.contains(tag)) {
|
|
135
|
+
moved.insert(tag);
|
|
136
|
+
}
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
default: {
|
|
140
|
+
// Skip other mutation types. We are only interested in moves and deletions here.
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
for (const auto &mutation : mutations) {
|
|
147
|
+
maybeUpdateWindowDimensions(mutation);
|
|
148
|
+
switch (mutation.type) {
|
|
149
|
+
case ShadowViewMutation::Update: {
|
|
150
|
+
auto &node = lightNodes_[mutation.newChildShadowView.tag];
|
|
151
|
+
react_native_assert(node && "LightNode not found");
|
|
152
|
+
node->previous = mutation.oldChildShadowView;
|
|
153
|
+
#ifdef ANDROID
|
|
154
|
+
// TODO (future): We don't merge the root view as the currently stored version might not be accurate, because of the inconsequential initialization order of proxy and the surface
|
|
155
|
+
if (!isRoot(node) && node->current.props) {
|
|
156
|
+
// On android rawProps are used to store the diffed props so we need to merge them
|
|
157
|
+
// This should soon be replaced in RN with Props 2.0 (the diffing will be done at the end of the pipeline)
|
|
158
|
+
auto ¤tRawProps = node->current.props->rawProps;
|
|
159
|
+
auto mergedRawProps = folly::dynamic::merge(currentRawProps, mutation.newChildShadowView.props->rawProps);
|
|
160
|
+
node->current = mutation.newChildShadowView;
|
|
161
|
+
node->current.props =
|
|
162
|
+
getComponentDescriptorForShadowView(node->current)
|
|
163
|
+
.cloneProps(propsParserContext, mutation.newChildShadowView.props, RawProps(mergedRawProps));
|
|
164
|
+
} else {
|
|
165
|
+
node->current = mutation.newChildShadowView;
|
|
166
|
+
}
|
|
167
|
+
#else
|
|
168
|
+
node->current = mutation.newChildShadowView;
|
|
169
|
+
#endif // ANDROID
|
|
170
|
+
auto tag = mutation.newChildShadowView.tag;
|
|
171
|
+
if (layoutAnimationsManager_->hasLayoutAnimation(tag, LAYOUT)) {
|
|
172
|
+
layout_.push_back(node);
|
|
173
|
+
} else {
|
|
174
|
+
filteredMutations.push_back(mutation);
|
|
175
|
+
}
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
case ShadowViewMutation::Create: {
|
|
179
|
+
const auto &node = std::make_shared<LightNode>();
|
|
180
|
+
node->current = mutation.newChildShadowView;
|
|
181
|
+
react_native_assert(!lightNodes_.contains(mutation.newChildShadowView.tag) && "LightNode already exists");
|
|
182
|
+
|
|
183
|
+
lightNodes_[mutation.newChildShadowView.tag] = node;
|
|
184
|
+
filteredMutations.push_back(mutation);
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
case ShadowViewMutation::Delete: {
|
|
188
|
+
lightNodes_.erase(mutation.oldChildShadowView.tag);
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
case ShadowViewMutation::Insert: {
|
|
192
|
+
transferConfigFromNativeID(mutation.newChildShadowView.props->nativeId, mutation.newChildShadowView.tag);
|
|
193
|
+
auto &node = lightNodes_[mutation.newChildShadowView.tag];
|
|
194
|
+
auto &parent = lightNodes_[mutation.parentTag];
|
|
195
|
+
parent->children.insert(parent->children.begin() + mutation.index, node);
|
|
196
|
+
node->parent = parent;
|
|
197
|
+
const auto tag = mutation.newChildShadowView.tag;
|
|
198
|
+
if (moved.contains(tag) && layoutAnimationsManager_->hasLayoutAnimation(tag, LAYOUT)) {
|
|
199
|
+
filteredMutations.push_back(
|
|
200
|
+
ShadowViewMutation::InsertMutation(mutation.parentTag, node->previous, mutation.index));
|
|
201
|
+
} else if (layoutAnimationsManager_->hasLayoutAnimation(tag, ENTERING)) {
|
|
202
|
+
entering_.push_back(node);
|
|
203
|
+
filteredMutations.push_back(mutation);
|
|
204
|
+
} else {
|
|
205
|
+
filteredMutations.push_back(mutation);
|
|
206
|
+
}
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
case ShadowViewMutation::Remove: {
|
|
210
|
+
const auto &node = lightNodes_[mutation.oldChildShadowView.tag];
|
|
211
|
+
const auto tag = node->current.tag;
|
|
212
|
+
const auto parentTag = mutation.parentTag;
|
|
213
|
+
const auto &parent = lightNodes_[parentTag];
|
|
214
|
+
react_native_assert(
|
|
215
|
+
parent->children[mutation.index]->current.tag == mutation.oldChildShadowView.tag &&
|
|
216
|
+
"Indicies are wrong in Remove mutation");
|
|
217
|
+
|
|
218
|
+
if (deleted.contains(tag) && !deleted.contains(parentTag)) {
|
|
219
|
+
exiting_.push_back(node);
|
|
220
|
+
filteredMutations.push_back(mutation);
|
|
221
|
+
parent->children.erase(parent->children.begin() + mutation.index);
|
|
222
|
+
} else if (!deleted.contains(tag)) {
|
|
223
|
+
filteredMutations.push_back(mutation);
|
|
224
|
+
parent->children.erase(parent->children.begin() + mutation.index);
|
|
225
|
+
}
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
default: {
|
|
229
|
+
react_native_assert(false && "Unsupported mutation type");
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// MARK: Layout Animation Updates
|
|
237
|
+
|
|
238
|
+
std::optional<SurfaceId> LayoutAnimationsProxy_Experimental::progressLayoutAnimation(
|
|
239
|
+
int tag,
|
|
240
|
+
const jsi::Object &newStyle) {
|
|
241
|
+
ReanimatedSystraceSection s("progressLayoutAnimation");
|
|
242
|
+
const auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
243
|
+
const auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
244
|
+
|
|
245
|
+
if (layoutAnimationIt == layoutAnimations_.end()) {
|
|
246
|
+
return {};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
auto &layoutAnimation = layoutAnimationIt->second;
|
|
250
|
+
|
|
251
|
+
maybeRestoreOpacity(layoutAnimation, newStyle);
|
|
252
|
+
|
|
253
|
+
auto rawProps = std::make_shared<RawProps>(uiRuntime_, jsi::Value(uiRuntime_, newStyle));
|
|
254
|
+
|
|
255
|
+
const PropsParserContext propsParserContext{layoutAnimation.finalView.surfaceId, *contextContainer_};
|
|
256
|
+
#ifdef RN_SERIALIZABLE_STATE
|
|
257
|
+
rawProps = std::make_shared<RawProps>(
|
|
258
|
+
folly::dynamic::merge(layoutAnimation.finalView.props->rawProps, (folly::dynamic)*rawProps));
|
|
259
|
+
#endif
|
|
260
|
+
auto newProps = getComponentDescriptorForShadowView(layoutAnimation.finalView)
|
|
261
|
+
.cloneProps(propsParserContext, layoutAnimation.finalView.props, std::move(*rawProps));
|
|
262
|
+
auto &updateMap = surfaceManager.getUpdateMap(layoutAnimation.finalView.surfaceId);
|
|
263
|
+
updateMap.insert_or_assign(tag, UpdateValues{newProps, Frame(uiRuntime_, newStyle)});
|
|
264
|
+
|
|
265
|
+
return layoutAnimation.finalView.surfaceId;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
std::optional<SurfaceId> LayoutAnimationsProxy_Experimental::endLayoutAnimation(int tag, bool shouldRemove) {
|
|
269
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
270
|
+
auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
271
|
+
|
|
272
|
+
if (layoutAnimationIt == layoutAnimations_.end()) {
|
|
273
|
+
return {};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
auto &layoutAnimation = layoutAnimationIt->second;
|
|
277
|
+
|
|
278
|
+
// multiple layout animations can be triggered for a view
|
|
279
|
+
// one after the other, so we need to keep count of how many
|
|
280
|
+
// were actually triggered, so that we don't cleanup necessary
|
|
281
|
+
// structures too early
|
|
282
|
+
if (layoutAnimation.count > 1) {
|
|
283
|
+
layoutAnimation.count--;
|
|
284
|
+
return {};
|
|
285
|
+
}
|
|
286
|
+
finishedAnimationTags_.push_back(tag);
|
|
287
|
+
auto surfaceId = layoutAnimation.finalView.surfaceId;
|
|
288
|
+
|
|
289
|
+
if (sharedTransitionManager_->tagToName_.contains(tag)) {
|
|
290
|
+
auto sharedTag = sharedTransitionManager_->tagToName_[tag];
|
|
291
|
+
sharedTransitionManager_->containerTags_.erase(sharedTag);
|
|
292
|
+
|
|
293
|
+
sharedContainersToRemove_.push_back(tag);
|
|
294
|
+
tagsToRestore_.push_back(restoreMap_[tag][1]);
|
|
295
|
+
transformForNode_.clear();
|
|
296
|
+
}
|
|
297
|
+
if (!shouldRemove) {
|
|
298
|
+
return surfaceId;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
auto node = lightNodes_[tag];
|
|
302
|
+
react_native_assert(node && "LightNode not found");
|
|
303
|
+
|
|
304
|
+
node->state = DEAD;
|
|
305
|
+
lightNodes_.erase(tag);
|
|
306
|
+
deadNodes.insert(node);
|
|
307
|
+
|
|
308
|
+
return surfaceId;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
void LayoutAnimationsProxy_Experimental::handleRemovals(
|
|
312
|
+
ShadowViewMutationList &filteredMutations,
|
|
313
|
+
std::vector<std::shared_ptr<LightNode>> &roots) const {
|
|
314
|
+
ReanimatedSystraceSection s("handleRemovals");
|
|
315
|
+
// iterate from the end, so that children
|
|
316
|
+
// with higher indices appear first in the mutations list
|
|
317
|
+
for (auto it = roots.rbegin(); it != roots.rend(); it++) {
|
|
318
|
+
auto &node = *it;
|
|
319
|
+
|
|
320
|
+
const StartAnimationsRecursivelyConfig config = {
|
|
321
|
+
.shouldRemoveSubviewsWithoutAnimations = true,
|
|
322
|
+
.shouldAnimate = true,
|
|
323
|
+
.isScreenPop = false,
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
if (startAnimationsRecursively(node, filteredMutations, config)) {
|
|
327
|
+
auto parent = node->parent.lock();
|
|
328
|
+
react_native_assert(parent && "Parent node is nullptr");
|
|
329
|
+
// TODO (future): figure out a better way to handle this
|
|
330
|
+
// Currently we remove each view, and then if we want to animate it, reinsert it at the end.
|
|
331
|
+
// This is nice, but introduces extra mutations (which could have some side effects, like making a snapshot in RNScreens),
|
|
332
|
+
// and it changes the zIndex of animated views, which is different from what've had.
|
|
333
|
+
// The biggest convenience of this approach is that it is much easier to maintain indices of animated views, and handle reparentings.
|
|
334
|
+
|
|
335
|
+
auto current = node->current;
|
|
336
|
+
if (layoutAnimations_.contains(node->current.tag)) {
|
|
337
|
+
current = layoutAnimations_.at(node->current.tag).currentView;
|
|
338
|
+
}
|
|
339
|
+
filteredMutations.push_back(
|
|
340
|
+
ShadowViewMutation::InsertMutation(parent->current.tag, current, static_cast<int>(parent->children.size())));
|
|
341
|
+
parent->children.push_back(node);
|
|
342
|
+
if (node->state == UNDEFINED) {
|
|
343
|
+
node->state = WAITING;
|
|
344
|
+
}
|
|
345
|
+
} else {
|
|
346
|
+
maybeCancelAnimation(node->current.tag);
|
|
347
|
+
filteredMutations.push_back(ShadowViewMutation::DeleteMutation(node->current));
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
for (const auto &node : deadNodes) {
|
|
352
|
+
if (node->state != DELETED) {
|
|
353
|
+
auto parent = node->parent.lock();
|
|
354
|
+
react_native_assert(parent && "Parent node is nullptr");
|
|
355
|
+
auto index = parent->removeChild(node);
|
|
356
|
+
react_native_assert(index != -1 && "Dead node not found");
|
|
357
|
+
|
|
358
|
+
endAnimationsRecursively(node, index, filteredMutations);
|
|
359
|
+
maybeDropAncestors(parent, filteredMutations);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
deadNodes.clear();
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
void LayoutAnimationsProxy_Experimental::addOngoingAnimations(SurfaceId surfaceId, ShadowViewMutationList &mutations)
|
|
366
|
+
const {
|
|
367
|
+
ReanimatedSystraceSection s1("addOngoingAnimations");
|
|
368
|
+
auto &updateMap = surfaceManager.getUpdateMap(surfaceId);
|
|
369
|
+
#ifdef ANDROID
|
|
370
|
+
std::vector<int> tagsToUpdate;
|
|
371
|
+
tagsToUpdate.reserve(updateMap.size());
|
|
372
|
+
for (auto &[tag, updateValues] : updateMap) {
|
|
373
|
+
tagsToUpdate.push_back(tag);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
auto maybeCorrectedTags = preserveMountedTags_(tagsToUpdate);
|
|
377
|
+
if (!maybeCorrectedTags.has_value()) {
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
auto correctedTags = maybeCorrectedTags->get();
|
|
382
|
+
|
|
383
|
+
// since the map is not updated, we can assume that the ordering of tags in
|
|
384
|
+
// correctedTags matches the iterator
|
|
385
|
+
int i = -1;
|
|
386
|
+
#endif
|
|
387
|
+
for (auto &[tag, updateValues] : updateMap) {
|
|
388
|
+
#ifdef ANDROID
|
|
389
|
+
i++;
|
|
390
|
+
if (correctedTags[i] == -1) {
|
|
391
|
+
// skip views that have not been mounted yet
|
|
392
|
+
// on Android we start entering animations from the JS thread
|
|
393
|
+
// so it might happen, that the first frame of the animation goes through
|
|
394
|
+
// before the view is first mounted
|
|
395
|
+
// https://github.com/software-mansion/react-native-reanimated/issues/7493
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
#endif
|
|
399
|
+
|
|
400
|
+
const auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
401
|
+
|
|
402
|
+
if (layoutAnimationIt == layoutAnimations_.end()) {
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
auto &layoutAnimation = layoutAnimationIt->second;
|
|
407
|
+
layoutAnimation.isViewAlreadyMounted = true;
|
|
408
|
+
auto newView = layoutAnimation.finalView;
|
|
409
|
+
if (updateValues.newProps) {
|
|
410
|
+
newView.props = updateValues.newProps;
|
|
411
|
+
}
|
|
412
|
+
updateLayoutMetrics(newView.layoutMetrics, updateValues.frame);
|
|
413
|
+
|
|
414
|
+
mutations.push_back(
|
|
415
|
+
ShadowViewMutation::UpdateMutation(layoutAnimation.currentView, newView, layoutAnimation.parentTag));
|
|
416
|
+
layoutAnimation.currentView = newView;
|
|
417
|
+
}
|
|
418
|
+
updateMap.clear();
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
void LayoutAnimationsProxy_Experimental::endAnimationsRecursively(
|
|
422
|
+
const std::shared_ptr<LightNode> &node,
|
|
423
|
+
int index,
|
|
424
|
+
ShadowViewMutationList &mutations) const {
|
|
425
|
+
maybeCancelAnimation(node->current.tag);
|
|
426
|
+
node->state = DELETED;
|
|
427
|
+
// iterate from the end, so that children
|
|
428
|
+
// with higher indices appear first in the mutations list
|
|
429
|
+
|
|
430
|
+
const int childrenSize = static_cast<int>(node->children.size());
|
|
431
|
+
for (int i = childrenSize - 1; i >= 0; i--) {
|
|
432
|
+
auto &subNode = node->children[i];
|
|
433
|
+
if (subNode->state != DELETED) {
|
|
434
|
+
endAnimationsRecursively(subNode, i, mutations);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
node->children.clear();
|
|
438
|
+
|
|
439
|
+
const auto &parent = node->parent.lock();
|
|
440
|
+
react_native_assert(parent && "Parent node is nullptr");
|
|
441
|
+
mutations.push_back(ShadowViewMutation::RemoveMutation(parent->current.tag, node->current, index));
|
|
442
|
+
mutations.push_back(ShadowViewMutation::DeleteMutation(node->current));
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
void LayoutAnimationsProxy_Experimental::maybeDropAncestors(
|
|
446
|
+
const std::shared_ptr<LightNode> &node,
|
|
447
|
+
ShadowViewMutationList &cleanupMutations) const {
|
|
448
|
+
if (node->children.size() != 0 || node->state == ANIMATING || node->state == UNDEFINED) {
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
auto parent = node->parent.lock();
|
|
453
|
+
react_native_assert(parent && "Parent node is nullptr");
|
|
454
|
+
auto index = parent->removeChild(node);
|
|
455
|
+
react_native_assert(index != -1 && "Child node not found");
|
|
456
|
+
|
|
457
|
+
node->state = DELETED;
|
|
458
|
+
maybeCancelAnimation(node->current.tag);
|
|
459
|
+
cleanupMutations.push_back(ShadowViewMutation::RemoveMutation(parent->current.tag, node->current, index));
|
|
460
|
+
cleanupMutations.push_back(ShadowViewMutation::DeleteMutation(node->current));
|
|
461
|
+
maybeDropAncestors(parent, cleanupMutations);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const ComponentDescriptor &LayoutAnimationsProxy_Experimental::getComponentDescriptorForShadowView(
|
|
465
|
+
const ShadowView &shadowView) const {
|
|
466
|
+
return componentDescriptorRegistry_->at(shadowView.componentHandle);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
bool LayoutAnimationsProxy_Experimental::startAnimationsRecursively(
|
|
470
|
+
const std::shared_ptr<LightNode> &node,
|
|
471
|
+
ShadowViewMutationList &mutations,
|
|
472
|
+
StartAnimationsRecursivelyConfig config) const {
|
|
473
|
+
auto &[shouldRemoveSubviewsWithoutAnimations, shouldAnimate, isScreenPop] = config;
|
|
474
|
+
if (isRNSScreenOrStack(node)) {
|
|
475
|
+
isScreenPop = true;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
shouldAnimate = !isScreenPop && layoutAnimationsManager_->shouldAnimateExiting(node->current.tag, shouldAnimate);
|
|
479
|
+
|
|
480
|
+
const bool hasExitAnimation =
|
|
481
|
+
shouldAnimate && layoutAnimationsManager_->hasLayoutAnimation(node->current.tag, LayoutAnimationType::EXITING);
|
|
482
|
+
bool hasAnimatedChildren = false;
|
|
483
|
+
|
|
484
|
+
shouldRemoveSubviewsWithoutAnimations = shouldRemoveSubviewsWithoutAnimations && !hasExitAnimation;
|
|
485
|
+
std::vector<std::shared_ptr<LightNode>> toBeRemoved;
|
|
486
|
+
|
|
487
|
+
// iterate from the end, so that children
|
|
488
|
+
// with higher indices appear first in the mutations list
|
|
489
|
+
auto index = static_cast<int>(node->children.size());
|
|
490
|
+
for (auto it = node->children.rbegin(); it != node->children.rend(); it++) {
|
|
491
|
+
index--;
|
|
492
|
+
auto &subNode = *it;
|
|
493
|
+
if (subNode->state != UNDEFINED) {
|
|
494
|
+
if (shouldAnimate && subNode->state != DEAD) {
|
|
495
|
+
hasAnimatedChildren = true;
|
|
496
|
+
} else {
|
|
497
|
+
endAnimationsRecursively(subNode, index, mutations);
|
|
498
|
+
toBeRemoved.push_back(subNode);
|
|
499
|
+
}
|
|
500
|
+
} else if (startAnimationsRecursively(subNode, mutations, config)) {
|
|
501
|
+
hasAnimatedChildren = true;
|
|
502
|
+
} else if (shouldRemoveSubviewsWithoutAnimations) {
|
|
503
|
+
maybeCancelAnimation(subNode->current.tag);
|
|
504
|
+
mutations.push_back(ShadowViewMutation::RemoveMutation(node->current.tag, subNode->current, index));
|
|
505
|
+
toBeRemoved.push_back(subNode);
|
|
506
|
+
subNode->state = DELETED;
|
|
507
|
+
mutations.push_back(ShadowViewMutation::DeleteMutation(subNode->current));
|
|
508
|
+
} else {
|
|
509
|
+
subNode->state = WAITING;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
for (auto &subNode : toBeRemoved) {
|
|
514
|
+
node->removeChild(subNode);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
const bool wantAnimateExit = hasExitAnimation || hasAnimatedChildren;
|
|
518
|
+
|
|
519
|
+
if (hasExitAnimation) {
|
|
520
|
+
node->state = ANIMATING;
|
|
521
|
+
startExitingAnimation(node);
|
|
522
|
+
lightNodes_[node->current.tag] = node;
|
|
523
|
+
} else {
|
|
524
|
+
// TODO (future): add proper cleanup
|
|
525
|
+
// layoutAnimationsManager_->clearLayoutAnimationConfig(node->tag);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
return wantAnimateExit;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
void LayoutAnimationsProxy_Experimental::updateOngoingAnimationTarget(const int tag, const ShadowViewMutation &mutation)
|
|
532
|
+
const {
|
|
533
|
+
layoutAnimations_[tag].finalView = mutation.newChildShadowView;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
void LayoutAnimationsProxy_Experimental::maybeCancelAnimation(const int tag) const {
|
|
537
|
+
if (!layoutAnimations_.contains(tag)) {
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
layoutAnimations_.erase(tag);
|
|
541
|
+
uiScheduler_->scheduleOnUI([weakThis = weak_from_this(), tag]() {
|
|
542
|
+
auto strongThis = weakThis.lock();
|
|
543
|
+
if (!strongThis) {
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
auto &uiRuntime = strongThis->uiRuntime_;
|
|
548
|
+
strongThis->layoutAnimationsManager_->cancelLayoutAnimation(uiRuntime, tag);
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
void LayoutAnimationsProxy_Experimental::transferConfigFromNativeID(const std::string &nativeIdString, const int tag)
|
|
553
|
+
const {
|
|
554
|
+
if (nativeIdString.empty() || nativeIdString.length() > 9) {
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
auto nativeId = 0;
|
|
558
|
+
for (int i = 0; i < nativeIdString.length(); i++) {
|
|
559
|
+
if (nativeIdString[i] < '0' || nativeIdString[i] > '9') {
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
nativeId *= 10;
|
|
563
|
+
nativeId += nativeIdString[i] - '0';
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
layoutAnimationsManager_->transferConfigFromNativeID(nativeId, tag);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// When entering animations start, we temporarily set opacity to 0
|
|
570
|
+
// so that we can immediately insert the view at the right position
|
|
571
|
+
// and schedule the animation on the UI thread
|
|
572
|
+
ShadowView LayoutAnimationsProxy_Experimental::cloneViewWithoutOpacity(
|
|
573
|
+
const ShadowView &shadowView,
|
|
574
|
+
const PropsParserContext &propsParserContext) const {
|
|
575
|
+
auto newView = shadowView;
|
|
576
|
+
const folly::dynamic opacity = folly::dynamic::object("opacity", 0);
|
|
577
|
+
auto newProps =
|
|
578
|
+
getComponentDescriptorForShadowView(newView).cloneProps(propsParserContext, newView.props, RawProps(opacity));
|
|
579
|
+
newView.props = newProps;
|
|
580
|
+
return newView;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
ShadowView LayoutAnimationsProxy_Experimental::cloneViewWithOpacity(
|
|
584
|
+
const ShadowView &shadowView,
|
|
585
|
+
const PropsParserContext &propsParserContext) const {
|
|
586
|
+
auto newView = shadowView;
|
|
587
|
+
const auto &props = static_cast<const ViewProps &>(*newView.props);
|
|
588
|
+
const folly::dynamic opacity = folly::dynamic::object("opacity", props.opacity);
|
|
589
|
+
auto newProps =
|
|
590
|
+
getComponentDescriptorForShadowView(newView).cloneProps(propsParserContext, newView.props, RawProps(opacity));
|
|
591
|
+
newView.props = newProps;
|
|
592
|
+
return newView;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
void LayoutAnimationsProxy_Experimental::maybeRestoreOpacity(
|
|
596
|
+
reanimated::LayoutAnimation &layoutAnimation,
|
|
597
|
+
const jsi::Object &newStyle) const {
|
|
598
|
+
if (layoutAnimation.opacity && !newStyle.hasProperty(uiRuntime_, "opacity")) {
|
|
599
|
+
newStyle.setProperty(uiRuntime_, "opacity", jsi::Value(*layoutAnimation.opacity));
|
|
600
|
+
if (layoutAnimation.isViewAlreadyMounted) {
|
|
601
|
+
// We want to reset opacity only when we are sure that this update will be
|
|
602
|
+
// applied to the native view. Otherwise, we want to update opacity using
|
|
603
|
+
// the `restoreOpacityInCaseOfFlakyEnteringAnimation` method.
|
|
604
|
+
layoutAnimation.opacity.reset();
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
void LayoutAnimationsProxy_Experimental::maybeUpdateWindowDimensions(
|
|
610
|
+
const facebook::react::ShadowViewMutation &mutation) const {
|
|
611
|
+
if (mutation.type == ShadowViewMutation::Update &&
|
|
612
|
+
!std::strcmp(mutation.oldChildShadowView.componentName, RootComponentName)) {
|
|
613
|
+
surfaceManager.updateWindow(
|
|
614
|
+
mutation.newChildShadowView.tag,
|
|
615
|
+
mutation.newChildShadowView.layoutMetrics.frame.size.width,
|
|
616
|
+
mutation.newChildShadowView.layoutMetrics.frame.size.height);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
void LayoutAnimationsProxy_Experimental::cleanupAnimations(
|
|
621
|
+
ShadowViewMutationList &filteredMutations,
|
|
622
|
+
const PropsParserContext &propsParserContext,
|
|
623
|
+
SurfaceId surfaceId) const {
|
|
624
|
+
ReanimatedSystraceSection s("cleanupAnimations");
|
|
625
|
+
cleanupSharedTransitions(filteredMutations, propsParserContext, surfaceId);
|
|
626
|
+
|
|
627
|
+
#ifdef ANDROID
|
|
628
|
+
restoreOpacityInCaseOfFlakyEnteringAnimation(surfaceId);
|
|
629
|
+
#endif // ANDROID
|
|
630
|
+
for (const auto tag : finishedAnimationTags_) {
|
|
631
|
+
auto &updateMap = surfaceManager.getUpdateMap(surfaceId);
|
|
632
|
+
layoutAnimations_.erase(tag);
|
|
633
|
+
updateMap.erase(tag);
|
|
634
|
+
}
|
|
635
|
+
finishedAnimationTags_.clear();
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// MARK: Start Animation
|
|
639
|
+
|
|
640
|
+
ShadowView LayoutAnimationsProxy_Experimental::maybeCreateLayoutAnimation(
|
|
641
|
+
ShadowView &before,
|
|
642
|
+
const ShadowView &after,
|
|
643
|
+
const Tag parentTag) const {
|
|
644
|
+
auto count = 1;
|
|
645
|
+
const auto tag = after.tag;
|
|
646
|
+
auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
647
|
+
auto &oldView = before;
|
|
648
|
+
|
|
649
|
+
if (layoutAnimationIt != layoutAnimations_.end()) {
|
|
650
|
+
auto &layoutAnimation = layoutAnimationIt->second;
|
|
651
|
+
oldView = layoutAnimation.currentView;
|
|
652
|
+
count = layoutAnimation.count + 1;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
auto finalView = after;
|
|
656
|
+
auto currentView = oldView;
|
|
657
|
+
auto startView = oldView;
|
|
658
|
+
|
|
659
|
+
layoutAnimations_[tag] = {
|
|
660
|
+
.finalView = finalView,
|
|
661
|
+
.currentView = currentView,
|
|
662
|
+
.startView = startView,
|
|
663
|
+
.parentTag = parentTag,
|
|
664
|
+
.count = count,
|
|
665
|
+
};
|
|
666
|
+
|
|
667
|
+
return oldView;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
void LayoutAnimationsProxy_Experimental::startEnteringAnimation(const std::shared_ptr<LightNode> &node) const {
|
|
671
|
+
auto newChildShadowView = node->current;
|
|
672
|
+
const auto &finalView = newChildShadowView;
|
|
673
|
+
const auto ¤tView = newChildShadowView;
|
|
674
|
+
|
|
675
|
+
const auto &props = newChildShadowView.props;
|
|
676
|
+
auto &viewProps = static_cast<const ViewProps &>(*props);
|
|
677
|
+
const auto opacity = viewProps.opacity;
|
|
678
|
+
const auto &parent = node->parent.lock();
|
|
679
|
+
react_native_assert(parent && "Parent node is nullptr");
|
|
680
|
+
const auto parentTag = parent->current.tag;
|
|
681
|
+
|
|
682
|
+
uiScheduler_->scheduleOnUI(
|
|
683
|
+
[weakThis = weak_from_this(), finalView, currentView, newChildShadowView, parentTag, opacity]() {
|
|
684
|
+
auto strongThis = weakThis.lock();
|
|
685
|
+
if (!strongThis) {
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
Rect window;
|
|
690
|
+
const auto tag = newChildShadowView.tag;
|
|
691
|
+
{
|
|
692
|
+
auto lock = std::unique_lock<std::recursive_mutex>(strongThis->mutex);
|
|
693
|
+
strongThis->layoutAnimations_[tag] = {
|
|
694
|
+
.finalView = newChildShadowView,
|
|
695
|
+
.currentView = newChildShadowView,
|
|
696
|
+
.startView = newChildShadowView,
|
|
697
|
+
.parentTag = parentTag,
|
|
698
|
+
.opacity = opacity,
|
|
699
|
+
};
|
|
700
|
+
window = strongThis->surfaceManager.getWindow(newChildShadowView.surfaceId);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
const Snapshot values(newChildShadowView, window);
|
|
704
|
+
auto &uiRuntime = strongThis->uiRuntime_;
|
|
705
|
+
const jsi::Object yogaValues(uiRuntime);
|
|
706
|
+
yogaValues.setProperty(uiRuntime, "targetOriginX", values.x);
|
|
707
|
+
yogaValues.setProperty(uiRuntime, "targetGlobalOriginX", values.x);
|
|
708
|
+
yogaValues.setProperty(uiRuntime, "targetOriginY", values.y);
|
|
709
|
+
yogaValues.setProperty(uiRuntime, "targetGlobalOriginY", values.y);
|
|
710
|
+
yogaValues.setProperty(uiRuntime, "targetWidth", values.width);
|
|
711
|
+
yogaValues.setProperty(uiRuntime, "targetHeight", values.height);
|
|
712
|
+
yogaValues.setProperty(uiRuntime, "windowWidth", values.windowWidth);
|
|
713
|
+
yogaValues.setProperty(uiRuntime, "windowHeight", values.windowHeight);
|
|
714
|
+
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
715
|
+
uiRuntime, tag, LayoutAnimationType::ENTERING, yogaValues);
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
void LayoutAnimationsProxy_Experimental::startExitingAnimation(const std::shared_ptr<LightNode> &node) const {
|
|
720
|
+
auto &oldChildShadowView = node->current;
|
|
721
|
+
const auto surfaceId = oldChildShadowView.surfaceId;
|
|
722
|
+
const auto tag = oldChildShadowView.tag;
|
|
723
|
+
const auto &parent = node->parent.lock();
|
|
724
|
+
react_native_assert(parent && "Parent node is nullptr");
|
|
725
|
+
const auto parentTag = parent->current.tag;
|
|
726
|
+
|
|
727
|
+
uiScheduler_->scheduleOnUI([weakThis = weak_from_this(), tag, parentTag, oldChildShadowView, surfaceId]() {
|
|
728
|
+
auto strongThis = weakThis.lock();
|
|
729
|
+
if (!strongThis) {
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
auto oldView = oldChildShadowView;
|
|
734
|
+
Rect window{};
|
|
735
|
+
{
|
|
736
|
+
auto &mutex = strongThis->mutex;
|
|
737
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
738
|
+
oldView = strongThis->maybeCreateLayoutAnimation(oldView, oldView, parentTag);
|
|
739
|
+
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
const Snapshot values(oldView, window);
|
|
743
|
+
|
|
744
|
+
auto &uiRuntime = strongThis->uiRuntime_;
|
|
745
|
+
const jsi::Object yogaValues(uiRuntime);
|
|
746
|
+
yogaValues.setProperty(uiRuntime, "currentOriginX", values.x);
|
|
747
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginX", values.x);
|
|
748
|
+
yogaValues.setProperty(uiRuntime, "currentOriginY", values.y);
|
|
749
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginY", values.y);
|
|
750
|
+
yogaValues.setProperty(uiRuntime, "currentWidth", values.width);
|
|
751
|
+
yogaValues.setProperty(uiRuntime, "currentHeight", values.height);
|
|
752
|
+
yogaValues.setProperty(uiRuntime, "windowWidth", values.windowWidth);
|
|
753
|
+
yogaValues.setProperty(uiRuntime, "windowHeight", values.windowHeight);
|
|
754
|
+
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
755
|
+
uiRuntime, tag, LayoutAnimationType::EXITING, yogaValues);
|
|
756
|
+
strongThis->layoutAnimationsManager_->clearLayoutAnimationConfig(tag);
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
void LayoutAnimationsProxy_Experimental::startLayoutAnimation(const std::shared_ptr<LightNode> &node) const {
|
|
761
|
+
auto oldChildShadowView = node->previous;
|
|
762
|
+
auto newChildShadowView = node->current;
|
|
763
|
+
auto surfaceId = oldChildShadowView.surfaceId;
|
|
764
|
+
const auto tag = oldChildShadowView.tag;
|
|
765
|
+
const auto &parent = node->parent.lock();
|
|
766
|
+
react_native_assert(parent && "Parent node is nullptr");
|
|
767
|
+
const auto parentTag = parent->current.tag;
|
|
768
|
+
|
|
769
|
+
uiScheduler_->scheduleOnUI(
|
|
770
|
+
[weakThis = weak_from_this(), surfaceId, oldChildShadowView, newChildShadowView, parentTag, tag]() {
|
|
771
|
+
auto strongThis = weakThis.lock();
|
|
772
|
+
if (!strongThis) {
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
auto oldView = oldChildShadowView;
|
|
777
|
+
Rect window{};
|
|
778
|
+
{
|
|
779
|
+
auto &mutex = strongThis->mutex;
|
|
780
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
781
|
+
oldView = strongThis->maybeCreateLayoutAnimation(oldView, newChildShadowView, parentTag);
|
|
782
|
+
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
const Snapshot currentValues(oldView, window);
|
|
786
|
+
const Snapshot targetValues(newChildShadowView, window);
|
|
787
|
+
|
|
788
|
+
auto &uiRuntime = strongThis->uiRuntime_;
|
|
789
|
+
const jsi::Object yogaValues(uiRuntime);
|
|
790
|
+
yogaValues.setProperty(uiRuntime, "currentOriginX", currentValues.x);
|
|
791
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginX", currentValues.x);
|
|
792
|
+
yogaValues.setProperty(uiRuntime, "currentOriginY", currentValues.y);
|
|
793
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginY", currentValues.y);
|
|
794
|
+
yogaValues.setProperty(uiRuntime, "currentWidth", currentValues.width);
|
|
795
|
+
yogaValues.setProperty(uiRuntime, "currentHeight", currentValues.height);
|
|
796
|
+
yogaValues.setProperty(uiRuntime, "targetOriginX", targetValues.x);
|
|
797
|
+
yogaValues.setProperty(uiRuntime, "targetGlobalOriginX", targetValues.x);
|
|
798
|
+
yogaValues.setProperty(uiRuntime, "targetOriginY", targetValues.y);
|
|
799
|
+
yogaValues.setProperty(uiRuntime, "targetGlobalOriginY", targetValues.y);
|
|
800
|
+
yogaValues.setProperty(uiRuntime, "targetWidth", targetValues.width);
|
|
801
|
+
yogaValues.setProperty(uiRuntime, "targetHeight", targetValues.height);
|
|
802
|
+
yogaValues.setProperty(uiRuntime, "windowWidth", targetValues.windowWidth);
|
|
803
|
+
yogaValues.setProperty(uiRuntime, "windowHeight", targetValues.windowHeight);
|
|
804
|
+
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
805
|
+
uiRuntime, tag, LayoutAnimationType::LAYOUT, yogaValues);
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
void LayoutAnimationsProxy_Experimental::startSharedTransition(
|
|
810
|
+
const int tag,
|
|
811
|
+
const ShadowView &before,
|
|
812
|
+
const ShadowView &after,
|
|
813
|
+
SurfaceId surfaceId) const {
|
|
814
|
+
uiScheduler_->scheduleOnUI([weakThis = weak_from_this(), before, after, surfaceId, tag]() {
|
|
815
|
+
auto strongThis = weakThis.lock();
|
|
816
|
+
if (!strongThis) {
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
auto oldView = before;
|
|
821
|
+
Rect window{};
|
|
822
|
+
{
|
|
823
|
+
auto &mutex = strongThis->mutex;
|
|
824
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
825
|
+
oldView = strongThis->maybeCreateLayoutAnimation(oldView, after, surfaceId);
|
|
826
|
+
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
auto &uiRuntime = strongThis->uiRuntime_;
|
|
830
|
+
auto propsDiffer = PropsDiffer(uiRuntime, oldView, after);
|
|
831
|
+
|
|
832
|
+
const auto &propsDiff = propsDiffer.computeDiff(uiRuntime);
|
|
833
|
+
|
|
834
|
+
propsDiff.setProperty(uiRuntime, "windowWidth", window.width);
|
|
835
|
+
propsDiff.setProperty(uiRuntime, "windowHeight", window.height);
|
|
836
|
+
|
|
837
|
+
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
838
|
+
uiRuntime, tag, LayoutAnimationType::SHARED_ELEMENT_TRANSITION, propsDiff);
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
void LayoutAnimationsProxy_Experimental::startProgressTransition(
|
|
843
|
+
const int tag,
|
|
844
|
+
const ShadowView &before,
|
|
845
|
+
const ShadowView &after,
|
|
846
|
+
SurfaceId surfaceId) const {
|
|
847
|
+
uiScheduler_->scheduleOnUI([weakThis = weak_from_this(), before, after, surfaceId]() {
|
|
848
|
+
auto strongThis = weakThis.lock();
|
|
849
|
+
if (!strongThis) {
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
auto oldView = before;
|
|
854
|
+
Rect window{};
|
|
855
|
+
{
|
|
856
|
+
auto &mutex = strongThis->mutex;
|
|
857
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
858
|
+
oldView = strongThis->maybeCreateLayoutAnimation(oldView, after, surfaceId);
|
|
859
|
+
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
860
|
+
}
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
} // namespace reanimated
|