react-native 0.66.0 → 0.67.0-rc.2
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/Libraries/ActionSheetIOS/ActionSheetIOS.js +14 -1
- package/Libraries/ActionSheetIOS/NativeActionSheetManager.js +2 -0
- package/Libraries/Animated/AnimatedEvent.js +23 -4
- package/Libraries/Animated/NativeAnimatedHelper.js +2 -2
- package/Libraries/Animated/components/AnimatedImage.js +3 -3
- package/Libraries/Animated/components/AnimatedScrollView.js +3 -3
- package/Libraries/Animated/components/AnimatedText.js +3 -3
- package/Libraries/Animated/components/AnimatedView.js +1 -3
- package/Libraries/Animated/createAnimatedComponent.js +3 -34
- package/Libraries/Components/Button.js +3 -0
- package/Libraries/Components/DatePicker/DatePickerIOS.ios.js +3 -6
- package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +4 -7
- package/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js +1 -0
- package/Libraries/Components/ScrollView/ScrollView.js +17 -16
- package/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +268 -252
- package/Libraries/Components/View/View.js +1 -1
- package/Libraries/Components/View/ViewAccessibility.js +1 -1
- package/Libraries/Core/ExceptionsManager.js +45 -80
- package/Libraries/Core/ExtendedError.js +0 -1
- package/Libraries/Core/ReactNativeVersion.js +2 -2
- package/Libraries/Core/setUpBatchedBridge.js +1 -1
- package/Libraries/Core/setUpGlobals.js +2 -4
- package/Libraries/Core/setUpTimers.js +2 -2
- package/Libraries/Image/Image.ios.js +6 -0
- package/Libraries/Image/ImageBackground.js +10 -8
- package/Libraries/Image/ImageProps.js +28 -0
- package/Libraries/Image/RCTImageView.mm +4 -0
- package/Libraries/LogBox/Data/LogBoxData.js +18 -19
- package/Libraries/LogBox/UI/LogBoxImages/alert-triangle.png +0 -0
- package/Libraries/LogBox/UI/LogBoxImages/chevron-left.png +0 -0
- package/Libraries/LogBox/UI/LogBoxImages/chevron-right.png +0 -0
- package/Libraries/LogBox/UI/LogBoxImages/close.png +0 -0
- package/Libraries/LogBox/UI/LogBoxImages/loader.png +0 -0
- package/Libraries/NativeAnimation/Nodes/RCTPropsAnimatedNode.m +0 -3
- package/Libraries/NativeAnimation/RCTNativeAnimatedModule.mm +6 -3
- package/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.h +1 -2
- package/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm +2 -1
- package/Libraries/NewAppScreen/components/logo.png +0 -0
- package/Libraries/PermissionsAndroid/NativePermissionsAndroid.js +2 -1
- package/Libraries/PermissionsAndroid/PermissionsAndroid.js +2 -0
- package/Libraries/Pressability/Pressability.js +13 -13
- package/Libraries/Pressability/PressabilityPerformanceEventEmitter.js +1 -1
- package/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm +0 -1
- package/Libraries/ReactNative/AppRegistry.js +4 -2
- package/Libraries/Renderer/REVISION +1 -1
- package/Libraries/Renderer/implementations/ReactFabric-dev.fb.js +1569 -875
- package/Libraries/Renderer/implementations/ReactFabric-prod.fb.js +529 -319
- package/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js +570 -362
- package/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js +1592 -891
- package/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js +521 -311
- package/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js +562 -354
- package/Libraries/Share/Share.js +1 -1
- package/Libraries/StyleSheet/normalizeColor.js +2 -2
- package/Libraries/Text/TextInput/Multiline/RCTUITextView.m +4 -2
- package/Libraries/Text/TextInput/RCTBaseTextInputView.m +2 -12
- package/Libraries/Text/TextInput/RCTInputAccessoryViewContent.m +4 -11
- package/Libraries/Text/TextProps.js +1 -7
- package/Libraries/TurboModule/TurboModuleRegistry.js +1 -1
- package/Libraries/Utilities/HMRClient.js +1 -1
- package/README.md +1 -1
- package/React/Base/RCTBridge+Private.h +8 -0
- package/React/Base/RCTBridge.h +4 -0
- package/React/Base/RCTBridge.m +19 -7
- package/React/Base/RCTBridgeModule.h +2 -11
- package/React/Base/RCTBundleURLProvider.h +1 -1
- package/React/Base/RCTBundleURLProvider.mm +5 -3
- package/React/Base/RCTConstants.h +0 -6
- package/React/Base/RCTConstants.m +0 -15
- package/React/Base/RCTConvert.h +1 -1
- package/React/Base/RCTDefines.h +12 -3
- package/React/Base/RCTEventDispatcherProtocol.h +2 -0
- package/React/Base/RCTJSThread.h +29 -0
- package/React/Base/RCTJSThread.m +19 -0
- package/React/Base/RCTRootView.h +15 -0
- package/React/Base/RCTRootView.m +15 -0
- package/React/Base/RCTTouchHandler.m +1 -9
- package/React/Base/RCTUtils.h +3 -0
- package/React/Base/RCTUtils.m +14 -7
- package/React/Base/RCTVersion.m +2 -2
- package/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h +11 -0
- package/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm +35 -1
- package/React/CoreModules/RCTAccessibilityManager+Internal.h +24 -0
- package/React/CoreModules/RCTAccessibilityManager.mm +18 -3
- package/React/CoreModules/RCTActionSheetManager.mm +14 -5
- package/React/CoreModules/RCTAppearance.mm +3 -1
- package/React/CoreModules/RCTDevLoadingView.mm +5 -10
- package/React/CoreModules/RCTDevSettings.mm +6 -6
- package/React/CoreModules/RCTDevSplitBundleLoader.mm +1 -1
- package/React/CoreModules/RCTDeviceInfo.mm +4 -4
- package/React/CoreModules/RCTEventDispatcher.mm +5 -0
- package/React/CoreModules/RCTExceptionsManager.mm +11 -24
- package/React/CoreModules/RCTPerfMonitor.mm +9 -4
- package/React/CoreModules/RCTRedBox.mm +1 -5
- package/React/CxxBridge/RCTCxxBridge.mm +18 -1
- package/React/DevSupport/RCTPackagerConnection.h +3 -0
- package/React/DevSupport/RCTPackagerConnection.mm +9 -5
- package/React/FBReactNativeSpec/FBReactNativeSpec.podspec +11 -3
- package/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm +0 -3
- package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +16 -0
- package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h +6 -0
- package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +3 -5
- package/React/Fabric/Mounting/RCTMountingManager.mm +15 -1
- package/React/Fabric/RCTScheduler.mm +12 -5
- package/React/Fabric/RCTSurfacePresenter.mm +0 -4
- package/React/Fabric/RCTSurfaceTouchHandler.mm +6 -20
- package/React/Fabric/Surface/RCTFabricSurface.mm +1 -3
- package/React/React-RCTFabric.podspec +0 -1
- package/React/Views/RCTFont.mm +54 -38
- package/React/Views/RCTView.m +1 -6
- package/React/Views/RCTViewManager.m +3 -2
- package/React/Views/SafeAreaView/RCTSafeAreaView.m +1 -5
- package/React/Views/ScrollView/RCTScrollView.m +5 -15
- package/React/Views/ScrollView/RCTScrollViewManager.m +0 -7
- package/React/Views/UIView+React.m +2 -11
- package/React-Core.podspec +0 -1
- package/ReactAndroid/build.gradle +11 -5
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK +0 -1
- package/ReactAndroid/src/androidTest/js/TestBundle.js +0 -7
- package/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/BUCK +2 -1
- package/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java +14 -8
- package/ReactAndroid/src/main/java/com/facebook/react/BUCK +0 -1
- package/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.java +7 -0
- package/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java +7 -0
- package/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +63 -26
- package/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java +50 -2
- package/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java +31 -0
- package/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java +17 -1
- package/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java +2 -0
- package/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java +13 -2
- package/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +1 -0
- package/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactCxxErrorHandler.java +39 -0
- package/ReactAndroid/src/main/java/com/facebook/react/bridge/RuntimeScheduler.java +21 -0
- package/ReactAndroid/src/main/java/com/facebook/react/common/BUCK +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/common/SurfaceDelegate.java +40 -0
- package/ReactAndroid/src/main/java/com/facebook/react/common/SurfaceDelegateFactory.java +24 -0
- package/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/jni/BUCK +0 -6
- package/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +16 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/BUCK +1 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java +5 -2
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DefaultDevSupportManagerFactory.java +102 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java +35 -11
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerFactory.java +5 -72
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DisabledDevSupportManager.java +12 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/LogBoxDialogSurfaceDelegate.java +92 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/LogBoxModule.java +27 -42
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/DevSupportManager.java +14 -0
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/Binding.java +5 -4
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java +3 -7
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +41 -2
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/events/EventEmitterWrapper.java +8 -3
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/events/FabricEventEmitter.java +43 -9
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Android.mk +2 -1
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeatV2.cpp +69 -0
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeatV2.h +40 -0
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/BUCK +2 -6
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp +84 -32
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.h +4 -2
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/EventEmitterWrapper.cpp +20 -2
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/EventEmitterWrapper.h +2 -1
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java +9 -1
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java +19 -4
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/IntBufferBatchMountItem.java +6 -2
- package/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/BUCK +2 -1
- package/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/JSCExecutor.java +6 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/appearance/AppearanceModule.java +10 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/blob/jni/BUCK +0 -6
- package/ReactAndroid/src/main/java/com/facebook/react/modules/clipboard/BUCK +4 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/clipboard/ClipboardModule.java +9 -8
- package/ReactAndroid/src/main/java/com/facebook/react/modules/core/ExceptionsManagerModule.java +7 -19
- package/ReactAndroid/src/main/java/com/facebook/react/modules/core/{JavaScriptTimerManager.java → JavaScriptTimerExecutor.java} +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.java +7 -7
- package/ReactAndroid/src/main/java/com/facebook/react/modules/core/TimingModule.java +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/modules/i18nmanager/I18nManagerModule.java +7 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/intent/IntentModule.java +23 -19
- package/ReactAndroid/src/main/java/com/facebook/react/modules/network/ForwardingCookieHandler.java +1 -4
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/ReconnectingWebSocket.java +8 -8
- package/ReactAndroid/src/main/java/com/facebook/react/processing/ReactPropertyProcessor.java +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/reactperflogger/jni/BUCK +0 -6
- package/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK +0 -1
- package/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java +0 -5
- package/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/BUCK +0 -12
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSTouchDispatcher.java +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/TouchTargetHelper.java +75 -10
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/Event.java +19 -22
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/EventCategoryDef.java +42 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/EventDispatcherImpl.java +7 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/LockFreeEventDispatcherImpl.java +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/RCTEventEmitter.java +7 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/RCTModernEventEmitter.java +2 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/ReactEventEmitter.java +17 -9
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchEvent.java +43 -8
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchEventType.java +15 -16
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchesHelper.java +108 -19
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/jni/BUCK +0 -6
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +79 -4
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java +5 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +94 -3
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java +21 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java +5 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java +0 -4
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java +16 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +9 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java +20 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java +25 -6
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java +25 -5
- package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditTextInputConnectionWrapper.java +3 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/CanvasUtil.java +92 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java +8 -8
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +19 -0
- package/ReactAndroid/src/main/jni/react/jni/Android.mk +3 -2
- package/ReactAndroid/src/main/jni/react/jni/BUCK +4 -5
- package/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp +49 -7
- package/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h +15 -2
- package/ReactAndroid/src/main/jni/react/jni/JReactCxxErrorHandler.cpp +18 -0
- package/ReactAndroid/src/main/jni/react/jni/JReactCxxErrorHandler.h +25 -0
- package/{ReactCommon/react/renderer/core/Constants.cpp → ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.cpp} +6 -8
- package/ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.h +30 -0
- package/ReactAndroid/src/main/jni/react/perftests/BUCK +0 -4
- package/ReactAndroid/src/main/third-party/android/androidx/BUCK +6 -6
- package/ReactAndroid/src/test/java/com/facebook/react/RootViewTest.java +43 -0
- package/ReactAndroid/src/test/java/com/facebook/react/modules/clipboard/ClipboardModuleTest.java +3 -1
- package/ReactCommon/React-Fabric.podspec +9 -1
- package/ReactCommon/better/BUCK +0 -6
- package/ReactCommon/callinvoker/BUCK +2 -8
- package/ReactCommon/cxxreact/BUCK +1 -16
- package/ReactCommon/cxxreact/ReactNativeVersion.h +2 -2
- package/ReactCommon/hermes/inspector/tools/msggen/package.json +7 -4
- package/ReactCommon/hermes/inspector/tools/msggen/yarn.lock +13 -10
- package/ReactCommon/jsi/BUCK +0 -9
- package/ReactCommon/jsinspector/BUCK +0 -5
- package/ReactCommon/logger/BUCK +0 -5
- package/ReactCommon/react/config/BUCK +0 -6
- package/ReactCommon/react/debug/BUCK +0 -6
- package/ReactCommon/react/nativemodule/core/BUCK +0 -5
- package/ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModuleManager.mm +14 -31
- package/ReactCommon/react/nativemodule/samples/BUCK +0 -7
- package/ReactCommon/react/renderer/animations/BUCK +1 -4
- package/ReactCommon/react/renderer/animations/LayoutAnimationCallbackWrapper.h +34 -0
- package/ReactCommon/react/renderer/animations/LayoutAnimationDriver.cpp +5 -26
- package/ReactCommon/react/renderer/animations/LayoutAnimationDriver.h +8 -14
- package/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp +912 -1147
- package/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.h +80 -245
- package/ReactCommon/react/renderer/animations/conversions.h +212 -0
- package/ReactCommon/react/renderer/animations/primitives.h +104 -0
- package/ReactCommon/react/renderer/animations/tests/LayoutAnimationTest.cpp +3 -3
- package/ReactCommon/react/renderer/animations/utils.cpp +71 -0
- package/ReactCommon/react/renderer/animations/utils.h +80 -0
- package/ReactCommon/react/renderer/attributedstring/AttributedString.h +0 -1
- package/ReactCommon/react/renderer/attributedstring/BUCK +0 -6
- package/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp +7 -3
- package/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h +12 -2
- package/ReactCommon/react/renderer/attributedstring/TextAttributes.h +1 -1
- package/ReactCommon/react/renderer/attributedstring/conversions.h +58 -3
- package/ReactCommon/react/renderer/attributedstring/primitives.h +18 -1
- package/ReactCommon/react/renderer/componentregistry/BUCK +0 -6
- package/ReactCommon/react/renderer/componentregistry/native/BUCK +0 -6
- package/ReactCommon/react/renderer/components/image/BUCK +0 -6
- package/ReactCommon/react/renderer/components/image/ImageComponentDescriptor.h +0 -2
- package/ReactCommon/react/renderer/components/inputaccessory/BUCK +0 -6
- package/ReactCommon/react/renderer/components/inputaccessory/InputAccessoryComponentDescriptor.h +0 -4
- package/ReactCommon/react/renderer/components/legacyviewmanagerinterop/BUCK +0 -6
- package/ReactCommon/react/renderer/components/modal/BUCK +0 -6
- package/ReactCommon/react/renderer/components/modal/ModalHostViewComponentDescriptor.h +0 -5
- package/ReactCommon/react/renderer/components/progressbar/BUCK +0 -6
- package/ReactCommon/react/renderer/components/progressbar/android/react/renderer/components/progressbar/AndroidProgressBarComponentDescriptor.h +0 -3
- package/ReactCommon/react/renderer/components/root/BUCK +0 -6
- package/ReactCommon/react/renderer/components/safeareaview/BUCK +0 -6
- package/ReactCommon/react/renderer/components/scrollview/BUCK +0 -6
- package/ReactCommon/react/renderer/components/slider/BUCK +0 -6
- package/ReactCommon/react/renderer/components/slider/SliderComponentDescriptor.h +0 -3
- package/ReactCommon/react/renderer/components/switch/BUCK +0 -6
- package/ReactCommon/react/renderer/components/switch/androidswitch/react/renderer/components/androidswitch/AndroidSwitchComponentDescriptor.h +0 -3
- package/ReactCommon/react/renderer/components/text/BUCK +0 -6
- package/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.h +1 -20
- package/ReactCommon/react/renderer/components/textinput/BUCK +0 -6
- package/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h +0 -3
- package/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h +2 -0
- package/ReactCommon/react/renderer/components/textinput/iostextinput/BUCK +0 -6
- package/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputComponentDescriptor.h +0 -3
- package/ReactCommon/react/renderer/components/unimplementedview/BUCK +0 -6
- package/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewComponentDescriptor.cpp +0 -4
- package/ReactCommon/react/renderer/components/view/Android.mk +1 -1
- package/ReactCommon/react/renderer/components/view/BUCK +0 -6
- package/ReactCommon/react/renderer/components/view/Touch.h +1 -32
- package/ReactCommon/react/renderer/components/view/ViewComponentDescriptor.h +0 -23
- package/ReactCommon/react/renderer/components/view/ViewPropsInterpolation.h +2 -3
- package/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp +3 -3
- package/ReactCommon/react/renderer/components/view/ViewShadowNode.h +1 -1
- package/ReactCommon/react/renderer/components/view/accessibilityPropsConversions.h +4 -0
- package/ReactCommon/react/renderer/core/BUCK +2 -6
- package/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h +14 -9
- package/ReactCommon/react/renderer/core/ConcreteShadowNode.h +1 -10
- package/ReactCommon/react/renderer/core/EventEmitter.cpp +9 -4
- package/ReactCommon/react/renderer/core/EventEmitter.h +2 -1
- package/ReactCommon/react/renderer/core/Props.h +1 -0
- package/ReactCommon/react/renderer/core/PropsParserContext.h +3 -2
- package/ReactCommon/react/renderer/core/RawEvent.h +7 -5
- package/ReactCommon/react/renderer/core/RawPropsKey.cpp +10 -2
- package/ReactCommon/react/renderer/core/ReactPrimitives.h +0 -2
- package/ReactCommon/react/renderer/core/ShadowNode.cpp +7 -10
- package/ReactCommon/react/renderer/core/ShadowNodeFamily.h +1 -0
- package/ReactCommon/react/renderer/debug/BUCK +0 -6
- package/ReactCommon/react/renderer/element/BUCK +0 -6
- package/ReactCommon/react/renderer/graphics/Android.mk +1 -1
- package/ReactCommon/react/renderer/graphics/BUCK +0 -6
- package/ReactCommon/react/renderer/graphics/React-graphics.podspec +0 -1
- package/ReactCommon/react/renderer/graphics/Transform.cpp +1 -1
- package/ReactCommon/react/renderer/graphics/Transform.h +1 -1
- package/ReactCommon/react/renderer/imagemanager/BUCK +0 -6
- package/ReactCommon/react/renderer/leakchecker/BUCK +0 -6
- package/ReactCommon/react/renderer/mapbuffer/BUCK +0 -6
- package/ReactCommon/react/renderer/mounting/Android.mk +2 -1
- package/ReactCommon/react/renderer/mounting/BUCK +0 -6
- package/ReactCommon/react/renderer/mounting/MountingOverrideDelegate.h +1 -1
- package/ReactCommon/react/renderer/mounting/ShadowViewMutation.cpp +12 -0
- package/ReactCommon/react/renderer/mounting/ShadowViewMutation.h +10 -1
- package/ReactCommon/react/renderer/runtimescheduler/Android.mk +2 -1
- package/ReactCommon/react/renderer/runtimescheduler/BUCK +1 -7
- package/ReactCommon/react/renderer/runtimescheduler/ErrorUtils.h +36 -0
- package/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp +28 -20
- package/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h +4 -2
- package/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp +4 -3
- package/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.h +4 -2
- package/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.cpp +32 -0
- package/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.h +36 -0
- package/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerClock.h +4 -2
- package/ReactCommon/react/renderer/runtimescheduler/SchedulerPriority.h +4 -3
- package/ReactCommon/react/renderer/runtimescheduler/Task.cpp +4 -2
- package/ReactCommon/react/renderer/runtimescheduler/Task.h +4 -2
- package/ReactCommon/react/renderer/runtimescheduler/primitives.h +4 -2
- package/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp +26 -1
- package/ReactCommon/react/renderer/runtimescheduler/tests/StubErrorUtils.h +72 -0
- package/ReactCommon/react/renderer/scheduler/BUCK +0 -6
- package/ReactCommon/react/renderer/scheduler/Scheduler.cpp +1 -4
- package/ReactCommon/react/renderer/scheduler/Scheduler.h +1 -1
- package/ReactCommon/react/renderer/scheduler/SurfaceHandler.h +4 -4
- package/ReactCommon/react/renderer/telemetry/BUCK +0 -6
- package/ReactCommon/react/renderer/templateprocessor/BUCK +0 -6
- package/ReactCommon/react/renderer/textlayoutmanager/BUCK +0 -6
- package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.h +2 -0
- package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm +19 -0
- package/ReactCommon/react/renderer/timeline/BUCK +6 -12
- package/ReactCommon/react/renderer/uimanager/BUCK +0 -6
- package/ReactCommon/react/renderer/uimanager/UIManagerAnimationDelegate.h +1 -1
- package/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp +2 -2
- package/ReactCommon/react/renderer/uimanager/UIManagerBinding.h +1 -1
- package/ReactCommon/react/test_utils/BUCK +3 -6
- package/ReactCommon/react/{renderer/core/Constants.h → test_utils/MockSurfaceHandler.h} +9 -7
- package/ReactCommon/react/utils/BUCK +0 -6
- package/ReactCommon/react/utils/ContextContainer.h +0 -27
- package/ReactCommon/reactperflogger/BUCK +0 -4
- package/ReactCommon/runtimeexecutor/BUCK +0 -6
- package/ReactCommon/yoga/BUCK +1 -5
- package/android/com/facebook/react/react-native/{0.66.0/react-native-0.66.0.aar → 0.67.0-rc.2/react-native-0.67.0-rc.2.aar} +0 -0
- package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.aar.md5 +1 -0
- package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.aar.sha1 +1 -0
- package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.aar.sha256 +1 -0
- package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.aar.sha512 +1 -0
- package/android/com/facebook/react/react-native/{0.66.0/react-native-0.66.0.module → 0.67.0-rc.2/react-native-0.67.0-rc.2.module} +16 -17
- package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.module.md5 +1 -0
- package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.module.sha1 +1 -0
- package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.module.sha256 +1 -0
- package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.module.sha512 +1 -0
- package/android/com/facebook/react/react-native/{0.66.0/react-native-0.66.0.pom → 0.67.0-rc.2/react-native-0.67.0-rc.2.pom} +2 -2
- package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.pom.md5 +1 -0
- package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.pom.sha1 +1 -0
- package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.pom.sha256 +1 -0
- package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.pom.sha512 +1 -0
- package/android/com/facebook/react/react-native/maven-metadata.xml +4 -4
- package/android/com/facebook/react/react-native/maven-metadata.xml.md5 +1 -1
- package/android/com/facebook/react/react-native/maven-metadata.xml.sha1 +1 -1
- package/android/com/facebook/react/react-native/maven-metadata.xml.sha256 +1 -1
- package/android/com/facebook/react/react-native/maven-metadata.xml.sha512 +1 -1
- package/flow/global.js +45 -0
- package/index.js +15 -10
- package/jest/mockModal.js +31 -0
- package/jest/setup.js +5 -3
- package/package.json +8 -9
- package/react.gradle +53 -18
- package/scripts/find-node.sh +13 -0
- package/scripts/generate-specs-cli.js +18 -0
- package/scripts/ios-configure-glog.sh +4 -0
- package/scripts/react-native-xcode.sh +7 -7
- package/scripts/react_native_pods.rb +200 -57
- package/template/Gemfile +6 -0
- package/template/Gemfile.lock +100 -0
- package/template/_bundle/config +2 -0
- package/template/_flowconfig +1 -1
- package/template/_ruby-version +1 -0
- package/template/android/app/build.gradle +1 -1
- package/template/android/app/src/main/res/drawable/rn_edit_text_material.xml +36 -0
- package/template/android/app/src/main/res/values/styles.xml +1 -0
- package/template/android/build.gradle +7 -3
- package/template/android/gradle/wrapper/gradle-wrapper.properties +1 -1
- package/template/android/gradle.properties +1 -1
- package/template/ios/HelloWorld.xcodeproj/project.pbxproj +0 -2
- package/template/package.json +1 -1
- package/third-party-podspecs/RCT-Folly.podspec +1 -1
- package/third-party-podspecs/glog.podspec +0 -1
- package/Libraries/Components/DatePickerAndroid/DatePickerAndroid.android.js +0 -87
- package/Libraries/Components/DatePickerAndroid/DatePickerAndroid.ios.js +0 -30
- package/Libraries/Components/DatePickerAndroid/DatePickerAndroidTypes.js +0 -30
- package/Libraries/Components/StaticContainer.react.js +0 -51
- package/Libraries/Components/Touchable/ensurePositiveDelayProps.js +0 -25
- package/Libraries/Interaction/InteractionMixin.js +0 -54
- package/Libraries/ReactNative/queryLayoutByID.js +0 -58
- package/ReactAndroid/src/androidTest/java/com/facebook/react/tests/DatePickerDialogTestCase.java +0 -172
- package/ReactAndroid/src/androidTest/js/DatePickerDialogTestModule.js +0 -45
- package/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/BUCK +0 -27
- package/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogFragment.java +0 -137
- package/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogModule.java +0 -153
- package/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerMode.java +0 -15
- package/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DismissableDatePickerDialog.java +0 -117
- package/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/BUCK +0 -20
- package/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/RuntimeSchedulerManager.java +0 -39
- package/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/Android.mk +0 -34
- package/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/BUCK +0 -35
- package/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/OnLoad.cpp +0 -15
- package/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.cpp +0 -46
- package/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.h +0 -40
- package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidViewPagerManagerDelegate.java +0 -57
- package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidViewPagerManagerInterface.java +0 -23
- package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/BUCK +0 -19
- package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/DatePickerManagerDelegate.java +0 -62
- package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/DatePickerManagerInterface.java +0 -25
- package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/InputAccessoryViewManagerDelegate.java +0 -33
- package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/InputAccessoryViewManagerInterface.java +0 -17
- package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/PullToRefreshViewManagerDelegate.java +0 -51
- package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/PullToRefreshViewManagerInterface.java +0 -21
- package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SwitchManagerDelegate.java +0 -63
- package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SwitchManagerInterface.java +0 -24
- package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.aar.md5 +0 -1
- package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.aar.sha1 +0 -1
- package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.aar.sha256 +0 -1
- package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.aar.sha512 +0 -1
- package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.module.md5 +0 -1
- package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.module.sha1 +0 -1
- package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.module.sha256 +0 -1
- package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.module.sha512 +0 -1
- package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.pom.md5 +0 -1
- package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.pom.sha1 +0 -1
- package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.pom.sha256 +0 -1
- package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.pom.sha512 +0 -1
- package/scripts/generate-specs.sh +0 -99
- package/template/_editorconfig +0 -3
- package/template/_gitattributes +0 -3
|
@@ -8,25 +8,24 @@
|
|
|
8
8
|
#include "LayoutAnimationKeyFrameManager.h"
|
|
9
9
|
|
|
10
10
|
#include <algorithm>
|
|
11
|
-
#include <chrono>
|
|
12
11
|
|
|
13
12
|
#include <react/debug/flags.h>
|
|
14
13
|
#include <react/debug/react_native_assert.h>
|
|
15
14
|
|
|
15
|
+
#include <logger/react_native_log.h>
|
|
16
|
+
#include <react/renderer/animations/conversions.h>
|
|
17
|
+
#include <react/renderer/animations/utils.h>
|
|
16
18
|
#include <react/renderer/componentregistry/ComponentDescriptorFactory.h>
|
|
19
|
+
#include <react/renderer/components/image/ImageProps.h>
|
|
17
20
|
#include <react/renderer/components/view/ViewProps.h>
|
|
18
21
|
#include <react/renderer/core/ComponentDescriptor.h>
|
|
19
22
|
#include <react/renderer/core/LayoutMetrics.h>
|
|
20
|
-
#include <react/renderer/core/LayoutableShadowNode.h>
|
|
21
23
|
#include <react/renderer/core/Props.h>
|
|
22
24
|
#include <react/renderer/core/PropsParserContext.h>
|
|
23
25
|
#include <react/renderer/core/RawValue.h>
|
|
24
26
|
#include <react/renderer/mounting/MountingCoordinator.h>
|
|
25
|
-
#include <react/renderer/mounting/ShadowViewMutation.h>
|
|
26
|
-
|
|
27
|
-
#include <react/renderer/mounting/Differentiator.h>
|
|
28
|
-
#include <react/renderer/mounting/ShadowTreeRevision.h>
|
|
29
27
|
#include <react/renderer/mounting/ShadowView.h>
|
|
28
|
+
#include <react/renderer/mounting/ShadowViewMutation.h>
|
|
30
29
|
|
|
31
30
|
#include <glog/logging.h>
|
|
32
31
|
|
|
@@ -74,6 +73,7 @@ void PrintMutationInstruction(
|
|
|
74
73
|
return stream;
|
|
75
74
|
}(LOG(ERROR));
|
|
76
75
|
}
|
|
76
|
+
|
|
77
77
|
void PrintMutationInstructionRelative(
|
|
78
78
|
std::string message,
|
|
79
79
|
ShadowViewMutation const &mutation,
|
|
@@ -85,199 +85,27 @@ void PrintMutationInstructionRelative(
|
|
|
85
85
|
}
|
|
86
86
|
#endif
|
|
87
87
|
|
|
88
|
-
static
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
if (param == "linear") {
|
|
93
|
-
return AnimationType::Linear;
|
|
94
|
-
}
|
|
95
|
-
if (param == "easeInEaseOut") {
|
|
96
|
-
return AnimationType::EaseInEaseOut;
|
|
97
|
-
}
|
|
98
|
-
if (param == "easeIn") {
|
|
99
|
-
return AnimationType::EaseIn;
|
|
100
|
-
}
|
|
101
|
-
if (param == "easeOut") {
|
|
102
|
-
return AnimationType::EaseOut;
|
|
103
|
-
}
|
|
104
|
-
if (param == "keyboard") {
|
|
105
|
-
return AnimationType::Keyboard;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
LOG(ERROR) << "Error parsing animation type: " << param;
|
|
109
|
-
return {};
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
static better::optional<AnimationProperty> parseAnimationProperty(
|
|
113
|
-
std::string param) {
|
|
114
|
-
if (param == "opacity") {
|
|
115
|
-
return AnimationProperty::Opacity;
|
|
116
|
-
}
|
|
117
|
-
if (param == "scaleX") {
|
|
118
|
-
return AnimationProperty::ScaleX;
|
|
119
|
-
}
|
|
120
|
-
if (param == "scaleY") {
|
|
121
|
-
return AnimationProperty::ScaleY;
|
|
122
|
-
}
|
|
123
|
-
if (param == "scaleXY") {
|
|
124
|
-
return AnimationProperty::ScaleXY;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
LOG(ERROR) << "Error parsing animation property: " << param;
|
|
128
|
-
return {};
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
static better::optional<AnimationConfig> parseAnimationConfig(
|
|
132
|
-
folly::dynamic const &config,
|
|
133
|
-
double defaultDuration,
|
|
134
|
-
bool parsePropertyType) {
|
|
135
|
-
if (config.empty() || !config.isObject()) {
|
|
136
|
-
return AnimationConfig{
|
|
137
|
-
AnimationType::Linear,
|
|
138
|
-
AnimationProperty::NotApplicable,
|
|
139
|
-
defaultDuration,
|
|
140
|
-
0,
|
|
141
|
-
0,
|
|
142
|
-
0};
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
auto const typeIt = config.find("type");
|
|
146
|
-
if (typeIt == config.items().end()) {
|
|
147
|
-
LOG(ERROR) << "Error parsing animation config: could not find field `type`";
|
|
148
|
-
return {};
|
|
149
|
-
}
|
|
150
|
-
auto const animationTypeParam = typeIt->second;
|
|
151
|
-
if (animationTypeParam.empty() || !animationTypeParam.isString()) {
|
|
152
|
-
LOG(ERROR)
|
|
153
|
-
<< "Error parsing animation config: could not unwrap field `type`";
|
|
154
|
-
return {};
|
|
155
|
-
}
|
|
156
|
-
const auto animationType = parseAnimationType(animationTypeParam.asString());
|
|
157
|
-
if (!animationType) {
|
|
158
|
-
LOG(ERROR)
|
|
159
|
-
<< "Error parsing animation config: could not parse field `type`";
|
|
160
|
-
return {};
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
AnimationProperty animationProperty = AnimationProperty::NotApplicable;
|
|
164
|
-
if (parsePropertyType) {
|
|
165
|
-
auto const propertyIt = config.find("property");
|
|
166
|
-
if (propertyIt == config.items().end()) {
|
|
167
|
-
LOG(ERROR)
|
|
168
|
-
<< "Error parsing animation config: could not find field `property`";
|
|
169
|
-
return {};
|
|
170
|
-
}
|
|
171
|
-
auto const animationPropertyParam = propertyIt->second;
|
|
172
|
-
if (animationPropertyParam.empty() || !animationPropertyParam.isString()) {
|
|
173
|
-
LOG(ERROR)
|
|
174
|
-
<< "Error parsing animation config: could not unwrap field `property`";
|
|
175
|
-
return {};
|
|
176
|
-
}
|
|
177
|
-
const auto animationPropertyParsed =
|
|
178
|
-
parseAnimationProperty(animationPropertyParam.asString());
|
|
179
|
-
if (!animationPropertyParsed) {
|
|
180
|
-
LOG(ERROR)
|
|
181
|
-
<< "Error parsing animation config: could not parse field `property`";
|
|
182
|
-
return {};
|
|
183
|
-
}
|
|
184
|
-
animationProperty = *animationPropertyParsed;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
double duration = defaultDuration;
|
|
188
|
-
double delay = 0;
|
|
189
|
-
double springDamping = 0.5;
|
|
190
|
-
double initialVelocity = 0;
|
|
191
|
-
|
|
192
|
-
auto const durationIt = config.find("duration");
|
|
193
|
-
if (durationIt != config.items().end()) {
|
|
194
|
-
if (durationIt->second.isDouble()) {
|
|
195
|
-
duration = durationIt->second.asDouble();
|
|
196
|
-
} else {
|
|
197
|
-
LOG(ERROR)
|
|
198
|
-
<< "Error parsing animation config: field `duration` must be a number";
|
|
199
|
-
return {};
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
auto const delayIt = config.find("delay");
|
|
204
|
-
if (delayIt != config.items().end()) {
|
|
205
|
-
if (delayIt->second.isDouble()) {
|
|
206
|
-
delay = delayIt->second.asDouble();
|
|
207
|
-
} else {
|
|
208
|
-
LOG(ERROR)
|
|
209
|
-
<< "Error parsing animation config: field `delay` must be a number";
|
|
210
|
-
return {};
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
auto const springDampingIt = config.find("springDamping");
|
|
215
|
-
if (springDampingIt != config.items().end() &&
|
|
216
|
-
springDampingIt->second.isDouble()) {
|
|
217
|
-
if (springDampingIt->second.isDouble()) {
|
|
218
|
-
springDamping = springDampingIt->second.asDouble();
|
|
219
|
-
} else {
|
|
220
|
-
LOG(ERROR)
|
|
221
|
-
<< "Error parsing animation config: field `springDamping` must be a number";
|
|
222
|
-
return {};
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
auto const initialVelocityIt = config.find("initialVelocity");
|
|
227
|
-
if (initialVelocityIt != config.items().end()) {
|
|
228
|
-
if (initialVelocityIt->second.isDouble()) {
|
|
229
|
-
initialVelocity = initialVelocityIt->second.asDouble();
|
|
230
|
-
} else {
|
|
231
|
-
LOG(ERROR)
|
|
232
|
-
<< "Error parsing animation config: field `initialVelocity` must be a number";
|
|
233
|
-
return {};
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
return better::optional<AnimationConfig>(AnimationConfig{
|
|
238
|
-
*animationType,
|
|
239
|
-
animationProperty,
|
|
240
|
-
duration,
|
|
241
|
-
delay,
|
|
242
|
-
springDamping,
|
|
243
|
-
initialVelocity});
|
|
88
|
+
static inline float
|
|
89
|
+
interpolateFloats(float coefficient, float oldValue, float newValue) {
|
|
90
|
+
return oldValue + (newValue - oldValue) * coefficient;
|
|
244
91
|
}
|
|
245
92
|
|
|
246
|
-
|
|
247
|
-
static better::optional<LayoutAnimationConfig> parseLayoutAnimationConfig(
|
|
248
|
-
folly::dynamic const &config) {
|
|
249
|
-
if (config.empty() || !config.isObject()) {
|
|
250
|
-
return {};
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
const auto durationIt = config.find("duration");
|
|
254
|
-
if (durationIt == config.items().end() || !durationIt->second.isDouble()) {
|
|
255
|
-
return {};
|
|
256
|
-
}
|
|
257
|
-
const double duration = durationIt->second.asDouble();
|
|
258
|
-
|
|
259
|
-
const auto createConfigIt = config.find("create");
|
|
260
|
-
const auto createConfig = createConfigIt == config.items().end()
|
|
261
|
-
? better::optional<AnimationConfig>(AnimationConfig{})
|
|
262
|
-
: parseAnimationConfig(createConfigIt->second, duration, true);
|
|
263
|
-
|
|
264
|
-
const auto updateConfigIt = config.find("update");
|
|
265
|
-
const auto updateConfig = updateConfigIt == config.items().end()
|
|
266
|
-
? better::optional<AnimationConfig>(AnimationConfig{})
|
|
267
|
-
: parseAnimationConfig(updateConfigIt->second, duration, false);
|
|
93
|
+
#pragma mark -
|
|
268
94
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
95
|
+
LayoutAnimationKeyFrameManager::LayoutAnimationKeyFrameManager(
|
|
96
|
+
RuntimeExecutor runtimeExecutor,
|
|
97
|
+
ContextContainer::Shared &contextContainer,
|
|
98
|
+
LayoutAnimationStatusDelegate *delegate)
|
|
99
|
+
: runtimeExecutor_(runtimeExecutor),
|
|
100
|
+
contextContainer_(contextContainer),
|
|
101
|
+
layoutAnimationStatusDelegate_(delegate),
|
|
102
|
+
now_([]() {
|
|
103
|
+
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
104
|
+
std::chrono::high_resolution_clock::now().time_since_epoch())
|
|
105
|
+
.count();
|
|
106
|
+
}) {}
|
|
273
107
|
|
|
274
|
-
|
|
275
|
-
return {};
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
return better::optional<LayoutAnimationConfig>(LayoutAnimationConfig{
|
|
279
|
-
duration, *createConfig, *updateConfig, *deleteConfig});
|
|
280
|
-
}
|
|
108
|
+
#pragma mark UIManagerAnimationDelegate methods
|
|
281
109
|
|
|
282
110
|
/**
|
|
283
111
|
* Globally configure next LayoutAnimation.
|
|
@@ -323,24 +151,9 @@ void LayoutAnimationKeyFrameManager::uiManagerDidConfigureNextLayoutAnimation(
|
|
|
323
151
|
}
|
|
324
152
|
}
|
|
325
153
|
|
|
326
|
-
void LayoutAnimationKeyFrameManager::
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
void LayoutAnimationKeyFrameManager::setLayoutAnimationStatusDelegate(
|
|
332
|
-
LayoutAnimationStatusDelegate *delegate) const {
|
|
333
|
-
std::lock_guard<std::mutex> lock(layoutAnimationStatusDelegateMutex_);
|
|
334
|
-
layoutAnimationStatusDelegate_ = delegate;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
bool LayoutAnimationKeyFrameManager::shouldOverridePullTransaction() const {
|
|
338
|
-
return shouldAnimateFrame();
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
void LayoutAnimationKeyFrameManager::stopSurface(SurfaceId surfaceId) {
|
|
342
|
-
std::lock_guard<std::mutex> lock(surfaceIdsToStopMutex_);
|
|
343
|
-
surfaceIdsToStop_.push_back(surfaceId);
|
|
154
|
+
void LayoutAnimationKeyFrameManager::setComponentDescriptorRegistry(
|
|
155
|
+
const SharedComponentDescriptorRegistry &componentDescriptorRegistry) {
|
|
156
|
+
componentDescriptorRegistry_ = componentDescriptorRegistry;
|
|
344
157
|
}
|
|
345
158
|
|
|
346
159
|
bool LayoutAnimationKeyFrameManager::shouldAnimateFrame() const {
|
|
@@ -348,608 +161,182 @@ bool LayoutAnimationKeyFrameManager::shouldAnimateFrame() const {
|
|
|
348
161
|
return currentAnimation_ || !inflightAnimations_.empty();
|
|
349
162
|
}
|
|
350
163
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
164
|
+
void LayoutAnimationKeyFrameManager::stopSurface(SurfaceId surfaceId) {
|
|
165
|
+
std::lock_guard<std::mutex> lock(surfaceIdsToStopMutex_);
|
|
166
|
+
surfaceIdsToStop_.insert(surfaceId);
|
|
354
167
|
}
|
|
355
168
|
|
|
356
|
-
|
|
357
|
-
LayoutAnimationKeyFrameManager::calculateAnimationProgress(
|
|
358
|
-
uint64_t now,
|
|
359
|
-
const LayoutAnimation &animation,
|
|
360
|
-
const AnimationConfig &mutationConfig) const {
|
|
361
|
-
if (mutationConfig.animationType == AnimationType::None) {
|
|
362
|
-
return {1, 1};
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
uint64_t startTime = animation.startTime;
|
|
366
|
-
uint64_t delay = mutationConfig.delay;
|
|
367
|
-
uint64_t endTime = startTime + delay + mutationConfig.duration;
|
|
368
|
-
|
|
369
|
-
static const float PI = 3.14159265358979323846;
|
|
370
|
-
|
|
371
|
-
if (now >= endTime) {
|
|
372
|
-
return {1, 1};
|
|
373
|
-
}
|
|
374
|
-
if (now < startTime + delay) {
|
|
375
|
-
return {0, 0};
|
|
376
|
-
}
|
|
169
|
+
#pragma mark - MountingOverrideDelegate methods
|
|
377
170
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
if (mutationConfig.animationType == AnimationType::Linear) {
|
|
382
|
-
return {linearTimeProgression, linearTimeProgression};
|
|
383
|
-
} else if (mutationConfig.animationType == AnimationType::EaseIn) {
|
|
384
|
-
// This is an accelerator-style interpolator.
|
|
385
|
-
// In the future, this parameter (2.0) could be adjusted. This has been the
|
|
386
|
-
// default for Classic RN forever.
|
|
387
|
-
return {linearTimeProgression, pow(linearTimeProgression, 2.0)};
|
|
388
|
-
} else if (mutationConfig.animationType == AnimationType::EaseOut) {
|
|
389
|
-
// This is an decelerator-style interpolator.
|
|
390
|
-
// In the future, this parameter (2.0) could be adjusted. This has been the
|
|
391
|
-
// default for Classic RN forever.
|
|
392
|
-
return {linearTimeProgression, 1.0 - pow(1 - linearTimeProgression, 2.0)};
|
|
393
|
-
} else if (mutationConfig.animationType == AnimationType::EaseInEaseOut) {
|
|
394
|
-
// This is a combination of accelerate+decelerate.
|
|
395
|
-
// The animation starts and ends slowly, and speeds up in the middle.
|
|
396
|
-
return {
|
|
397
|
-
linearTimeProgression,
|
|
398
|
-
cos((linearTimeProgression + 1.0) * PI) / 2 + 0.5};
|
|
399
|
-
} else if (mutationConfig.animationType == AnimationType::Spring) {
|
|
400
|
-
// Using mSpringDamping in this equation is not really the exact
|
|
401
|
-
// mathematical springDamping, but a good approximation We need to replace
|
|
402
|
-
// this equation with the right Factor that accounts for damping and
|
|
403
|
-
// friction
|
|
404
|
-
double damping = mutationConfig.springDamping;
|
|
405
|
-
return {
|
|
406
|
-
linearTimeProgression,
|
|
407
|
-
(1 +
|
|
408
|
-
pow(2, -10 * linearTimeProgression) *
|
|
409
|
-
sin((linearTimeProgression - damping / 4) * PI * 2 / damping))};
|
|
410
|
-
} else {
|
|
411
|
-
return {linearTimeProgression, linearTimeProgression};
|
|
412
|
-
}
|
|
171
|
+
bool LayoutAnimationKeyFrameManager::shouldOverridePullTransaction() const {
|
|
172
|
+
return shouldAnimateFrame();
|
|
413
173
|
}
|
|
414
174
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
// TODO: turn all of this into a lambda and share code?
|
|
426
|
-
if (mutation.mutatedViewIsVirtual()) {
|
|
427
|
-
PrintMutationInstruction(
|
|
428
|
-
"[IndexAdjustment] Not calling adjustImmediateMutationIndicesForDelayedMutations, is virtual, for:",
|
|
429
|
-
mutation);
|
|
430
|
-
return;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
PrintMutationInstruction(
|
|
434
|
-
"[IndexAdjustment] Calling adjustImmediateMutationIndicesForDelayedMutations for:",
|
|
435
|
-
mutation);
|
|
436
|
-
|
|
437
|
-
// First, collect all final mutations that could impact this immediate
|
|
438
|
-
// mutation.
|
|
439
|
-
std::vector<ShadowViewMutation *> candidateMutations{};
|
|
440
|
-
|
|
441
|
-
for (auto inflightAnimationIt =
|
|
442
|
-
inflightAnimations_.rbegin() + (skipLastAnimation ? 1 : 0);
|
|
443
|
-
inflightAnimationIt != inflightAnimations_.rend();
|
|
444
|
-
inflightAnimationIt++) {
|
|
445
|
-
auto &inflightAnimation = *inflightAnimationIt;
|
|
446
|
-
if (inflightAnimation.surfaceId != surfaceId) {
|
|
447
|
-
continue;
|
|
448
|
-
}
|
|
449
|
-
if (inflightAnimation.completed) {
|
|
450
|
-
continue;
|
|
451
|
-
}
|
|
175
|
+
better::optional<MountingTransaction>
|
|
176
|
+
LayoutAnimationKeyFrameManager::pullTransaction(
|
|
177
|
+
SurfaceId surfaceId,
|
|
178
|
+
MountingTransaction::Number transactionNumber,
|
|
179
|
+
TransactionTelemetry const &telemetry,
|
|
180
|
+
ShadowViewMutationList mutations) const {
|
|
181
|
+
simulateImagePropsMemoryAccess(mutations);
|
|
182
|
+
// Current time in milliseconds
|
|
183
|
+
uint64_t now = now_();
|
|
452
184
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
it++) {
|
|
456
|
-
auto &animatedKeyFrame = *it;
|
|
185
|
+
bool inflightAnimationsExistInitially = !inflightAnimations_.empty();
|
|
186
|
+
deleteAnimationsForStoppedSurfaces();
|
|
457
187
|
|
|
458
|
-
|
|
459
|
-
|
|
188
|
+
if (!mutations.empty()) {
|
|
189
|
+
#ifdef RN_SHADOW_TREE_INTROSPECTION
|
|
190
|
+
{
|
|
191
|
+
std::stringstream ss(getDebugDescription(mutations, {}));
|
|
192
|
+
std::string to;
|
|
193
|
+
while (std::getline(ss, to, '\n')) {
|
|
194
|
+
LOG(ERROR)
|
|
195
|
+
<< "LayoutAnimationKeyFrameManager.cpp: got mutation list: Line: "
|
|
196
|
+
<< to;
|
|
460
197
|
}
|
|
198
|
+
};
|
|
199
|
+
#endif
|
|
461
200
|
|
|
462
|
-
//
|
|
463
|
-
|
|
464
|
-
|
|
201
|
+
// DEBUG ONLY: list existing inflight animations
|
|
202
|
+
#ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
|
|
203
|
+
LOG(ERROR) << "BEGINNING DISPLAYING ONGOING inflightAnimations_!";
|
|
204
|
+
int i = 0;
|
|
205
|
+
int j = 0;
|
|
206
|
+
for (auto const &inflightAnimation : inflightAnimations_) {
|
|
207
|
+
i++;
|
|
208
|
+
j = 0;
|
|
209
|
+
if (inflightAnimation.completed) {
|
|
465
210
|
continue;
|
|
466
211
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
if (
|
|
470
|
-
continue;
|
|
471
|
-
}
|
|
472
|
-
if (delayedMutation.mutatedViewIsVirtual()) {
|
|
212
|
+
for (auto &keyframe : inflightAnimation.keyFrames) {
|
|
213
|
+
j++;
|
|
214
|
+
if (keyframe.invalidated) {
|
|
473
215
|
continue;
|
|
474
216
|
}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
217
|
+
for (const auto &finalMutationForKeyFrame :
|
|
218
|
+
keyframe.finalMutationsForKeyFrame) {
|
|
219
|
+
if (finalMutationForKeyFrame.mutatedViewIsVirtual()) {
|
|
220
|
+
std::string msg = "Animation " + std::to_string(i) + " keyframe " +
|
|
221
|
+
std::to_string(j) + ": Final Animation";
|
|
222
|
+
PrintMutationInstruction(msg, finalMutationForKeyFrame);
|
|
223
|
+
} else {
|
|
224
|
+
LOG(ERROR) << "Animation " << i << " keyframe " << j
|
|
225
|
+
<< ": on tag: [" << keyframe.viewStart.tag << "]";
|
|
226
|
+
}
|
|
479
227
|
}
|
|
480
|
-
|
|
481
|
-
PrintMutationInstructionRelative(
|
|
482
|
-
"[IndexAdjustment] adjustImmediateMutationIndicesForDelayedMutations CANDIDATE for:",
|
|
483
|
-
mutation,
|
|
484
|
-
delayedMutation);
|
|
485
|
-
candidateMutations.push_back(&delayedMutation);
|
|
486
228
|
}
|
|
487
229
|
}
|
|
230
|
+
LOG(ERROR) << "BEGINNING DONE DISPLAYING ONGOING inflightAnimations_!";
|
|
231
|
+
#endif
|
|
488
232
|
|
|
489
|
-
|
|
490
|
-
|
|
233
|
+
PropsParserContext propsParserContext{surfaceId, *contextContainer_};
|
|
234
|
+
|
|
235
|
+
// What to do if we detect a conflict? Get current value and make
|
|
236
|
+
// that the baseline of the next animation. Scale the remaining time
|
|
237
|
+
// in the animation
|
|
238
|
+
// Types of conflicts and how we handle them:
|
|
239
|
+
// Update -> update: remove the previous update, make it the baseline of the
|
|
240
|
+
// next update (with current progress) Update -> remove: same, with final
|
|
241
|
+
// mutation being a remove Insert -> update: treat as update->update Insert
|
|
242
|
+
// -> remove: same, as update->remove Remove -> update/insert: not possible
|
|
243
|
+
// We just collect pairs here of <Mutation, AnimationConfig> and delete them
|
|
244
|
+
// from active animations. If another animation is queued up from the
|
|
245
|
+
// current mutations then these deleted mutations will serve as the baseline
|
|
246
|
+
// for the next animation. If not, the current mutations are executed
|
|
247
|
+
// immediately without issues.
|
|
248
|
+
std::vector<AnimationKeyFrame> conflictingAnimations{};
|
|
249
|
+
getAndEraseConflictingAnimations(
|
|
250
|
+
surfaceId, mutations, conflictingAnimations);
|
|
251
|
+
|
|
252
|
+
// Are we animating this list of mutations?
|
|
253
|
+
better::optional<LayoutAnimation> currentAnimation{};
|
|
254
|
+
{
|
|
255
|
+
std::lock_guard<std::mutex> lock(currentAnimationMutex_);
|
|
256
|
+
if (currentAnimation_) {
|
|
257
|
+
currentAnimation = std::move(currentAnimation_);
|
|
258
|
+
currentAnimation_.reset();
|
|
259
|
+
}
|
|
491
260
|
}
|
|
492
|
-
}
|
|
493
261
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
int adjustedDelta = 0;
|
|
499
|
-
while (changed) {
|
|
500
|
-
changed = false;
|
|
501
|
-
candidateMutations.erase(
|
|
502
|
-
std::remove_if(
|
|
503
|
-
candidateMutations.begin(),
|
|
504
|
-
candidateMutations.end(),
|
|
505
|
-
[&changed, &mutation, &adjustedDelta, &isRemoveMutation](
|
|
506
|
-
ShadowViewMutation *candidateMutation) {
|
|
507
|
-
bool indexConflicts =
|
|
508
|
-
(candidateMutation->index < mutation.index ||
|
|
509
|
-
(isRemoveMutation &&
|
|
510
|
-
candidateMutation->index == mutation.index));
|
|
511
|
-
if (indexConflicts) {
|
|
512
|
-
mutation.index++;
|
|
513
|
-
adjustedDelta++;
|
|
514
|
-
changed = true;
|
|
515
|
-
PrintMutationInstructionRelative(
|
|
516
|
-
"[IndexAdjustment] adjustImmediateMutationIndicesForDelayedMutations: Adjusting mutation UPWARD",
|
|
517
|
-
mutation,
|
|
518
|
-
*candidateMutation);
|
|
519
|
-
return true;
|
|
520
|
-
}
|
|
521
|
-
return false;
|
|
522
|
-
}),
|
|
523
|
-
candidateMutations.end());
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
void LayoutAnimationKeyFrameManager::adjustDelayedMutationIndicesForMutation(
|
|
528
|
-
SurfaceId surfaceId,
|
|
529
|
-
ShadowViewMutation const &mutation,
|
|
530
|
-
bool skipLastAnimation) const {
|
|
531
|
-
bool isRemoveMutation = mutation.type == ShadowViewMutation::Type::Remove;
|
|
532
|
-
bool isInsertMutation = mutation.type == ShadowViewMutation::Type::Insert;
|
|
533
|
-
auto tag = isRemoveMutation ? mutation.oldChildShadowView.tag
|
|
534
|
-
: mutation.newChildShadowView.tag;
|
|
535
|
-
react_native_assert(isRemoveMutation || isInsertMutation);
|
|
536
|
-
|
|
537
|
-
if (mutation.mutatedViewIsVirtual()) {
|
|
538
|
-
PrintMutationInstruction(
|
|
539
|
-
"[IndexAdjustment] Not calling adjustDelayedMutationIndicesForMutation, is virtual, for:",
|
|
540
|
-
mutation);
|
|
541
|
-
return;
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
// First, collect all final mutations that could impact this immediate
|
|
545
|
-
// mutation.
|
|
546
|
-
std::vector<ShadowViewMutation *> candidateMutations{};
|
|
547
|
-
|
|
548
|
-
for (auto inflightAnimationIt =
|
|
549
|
-
inflightAnimations_.rbegin() + (skipLastAnimation ? 1 : 0);
|
|
550
|
-
inflightAnimationIt != inflightAnimations_.rend();
|
|
551
|
-
inflightAnimationIt++) {
|
|
552
|
-
auto &inflightAnimation = *inflightAnimationIt;
|
|
553
|
-
|
|
554
|
-
if (inflightAnimation.surfaceId != surfaceId) {
|
|
555
|
-
continue;
|
|
556
|
-
}
|
|
557
|
-
if (inflightAnimation.completed) {
|
|
558
|
-
continue;
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
for (auto it = inflightAnimation.keyFrames.begin();
|
|
562
|
-
it != inflightAnimation.keyFrames.end();
|
|
563
|
-
it++) {
|
|
564
|
-
auto &animatedKeyFrame = *it;
|
|
565
|
-
|
|
566
|
-
if (animatedKeyFrame.invalidated) {
|
|
567
|
-
continue;
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
// Detect if they're in the same view hierarchy, but not equivalent
|
|
571
|
-
// (We've already detected direct conflicts and handled them above)
|
|
572
|
-
if (animatedKeyFrame.parentView.tag != mutation.parentShadowView.tag) {
|
|
573
|
-
continue;
|
|
574
|
-
}
|
|
262
|
+
if (currentAnimation.hasValue()) {
|
|
263
|
+
LayoutAnimation animation = std::move(currentAnimation).value();
|
|
264
|
+
animation.surfaceId = surfaceId;
|
|
265
|
+
animation.startTime = now;
|
|
575
266
|
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
267
|
+
// Pre-process list to:
|
|
268
|
+
// Catch remove+reinsert (reorders)
|
|
269
|
+
// Catch delete+create (reparenting) (this should be optimized away at
|
|
270
|
+
// the diffing level eventually?)
|
|
271
|
+
// TODO: to prevent this step we could tag Remove/Insert mutations as
|
|
272
|
+
// being moves on the Differ level, since we know that there? We could use
|
|
273
|
+
// TinyMap here, but it's not exposed by Differentiator (yet).
|
|
274
|
+
better::set<Tag> insertedTags;
|
|
275
|
+
better::set<Tag> deletedTags;
|
|
276
|
+
better::set<Tag> reparentedTags; // tags that are deleted and recreated
|
|
277
|
+
std::unordered_map<Tag, ShadowViewMutation> movedTags;
|
|
278
|
+
for (const auto &mutation : mutations) {
|
|
279
|
+
if (mutation.type == ShadowViewMutation::Type::Insert) {
|
|
280
|
+
insertedTags.insert(mutation.newChildShadowView.tag);
|
|
580
281
|
}
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
continue;
|
|
282
|
+
if (mutation.type == ShadowViewMutation::Type::Delete) {
|
|
283
|
+
deletedTags.insert(mutation.oldChildShadowView.tag);
|
|
584
284
|
}
|
|
585
|
-
if (
|
|
586
|
-
|
|
285
|
+
if (mutation.type == ShadowViewMutation::Type::Create) {
|
|
286
|
+
if (deletedTags.find(mutation.newChildShadowView.tag) !=
|
|
287
|
+
deletedTags.end()) {
|
|
288
|
+
reparentedTags.insert(mutation.newChildShadowView.tag);
|
|
289
|
+
}
|
|
587
290
|
}
|
|
588
|
-
|
|
589
|
-
PrintMutationInstructionRelative(
|
|
590
|
-
"[IndexAdjustment] adjustDelayedMutationIndicesForMutation: CANDIDATE:",
|
|
591
|
-
mutation,
|
|
592
|
-
finalAnimationMutation);
|
|
593
|
-
candidateMutations.push_back(&finalAnimationMutation);
|
|
594
291
|
}
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
// Because the finalAnimations are not sorted in any way, it is possible to
|
|
599
|
-
// have some sequence like:
|
|
600
|
-
// * DELAYED REMOVE 10 from {TAG}
|
|
601
|
-
// * DELAYED REMOVE 9 from {TAG}
|
|
602
|
-
// * ...
|
|
603
|
-
// * DELAYED REMOVE 5 from {TAG}
|
|
604
|
-
// with mutation: INSERT 6/REMOVE 6. This would cause the first few mutations
|
|
605
|
-
// to *not* be adjusted, even though they would be impacted by mutation or
|
|
606
|
-
// vice-versa after later adjustments are applied. Therefore, we just keep
|
|
607
|
-
// recursing while there are any changes. This isn't great, but is good enough
|
|
608
|
-
// for now until we change these data-structures.
|
|
609
|
-
bool changed = true;
|
|
610
|
-
while (changed) {
|
|
611
|
-
changed = false;
|
|
612
|
-
candidateMutations.erase(
|
|
613
|
-
std::remove_if(
|
|
614
|
-
candidateMutations.begin(),
|
|
615
|
-
candidateMutations.end(),
|
|
616
|
-
[&mutation, &isRemoveMutation, &isInsertMutation, &changed](
|
|
617
|
-
ShadowViewMutation *candidateMutation) {
|
|
618
|
-
if (isRemoveMutation &&
|
|
619
|
-
mutation.index <= candidateMutation->index) {
|
|
620
|
-
candidateMutation->index--;
|
|
621
|
-
changed = true;
|
|
622
|
-
PrintMutationInstructionRelative(
|
|
623
|
-
"[IndexAdjustment] adjustDelayedMutationIndicesForMutation: Adjusting mutation DOWNWARD",
|
|
624
|
-
mutation,
|
|
625
|
-
*candidateMutation);
|
|
626
|
-
return true;
|
|
627
|
-
} else if (
|
|
628
|
-
isInsertMutation &&
|
|
629
|
-
mutation.index <= candidateMutation->index) {
|
|
630
|
-
candidateMutation->index++;
|
|
631
|
-
changed = true;
|
|
632
|
-
PrintMutationInstructionRelative(
|
|
633
|
-
"[IndexAdjustment] adjustDelayedMutationIndicesForMutation: Adjusting mutation UPWARD",
|
|
634
|
-
mutation,
|
|
635
|
-
*candidateMutation);
|
|
636
|
-
return true;
|
|
637
|
-
}
|
|
638
|
-
return false;
|
|
639
|
-
}),
|
|
640
|
-
candidateMutations.end());
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
void LayoutAnimationKeyFrameManager::getAndEraseConflictingAnimations(
|
|
645
|
-
SurfaceId surfaceId,
|
|
646
|
-
ShadowViewMutationList const &mutations,
|
|
647
|
-
std::vector<AnimationKeyFrame> &conflictingAnimations) const {
|
|
648
|
-
ShadowViewMutationList localConflictingMutations{};
|
|
649
|
-
for (auto const &mutation : mutations) {
|
|
650
|
-
bool mutationIsCreateOrDelete =
|
|
651
|
-
mutation.type == ShadowViewMutation::Type::Create ||
|
|
652
|
-
mutation.type == ShadowViewMutation::Type::Delete;
|
|
653
|
-
auto const &baselineShadowView =
|
|
654
|
-
(mutation.type == ShadowViewMutation::Type::Insert ||
|
|
655
|
-
mutation.type == ShadowViewMutation::Type::Create)
|
|
656
|
-
? mutation.newChildShadowView
|
|
657
|
-
: mutation.oldChildShadowView;
|
|
658
|
-
auto baselineTag = baselineShadowView.tag;
|
|
659
292
|
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
}
|
|
293
|
+
// Process mutations list into operations that can be sent to platform
|
|
294
|
+
// immediately, and those that need to be animated Deletions, removals,
|
|
295
|
+
// updates are delayed and animated. Creations and insertions are sent to
|
|
296
|
+
// platform and then "animated in" with opacity updates. Upon completion,
|
|
297
|
+
// removals and deletions are sent to platform
|
|
298
|
+
ShadowViewMutation::List immediateMutations;
|
|
667
299
|
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
300
|
+
// Remove operations that are actually moves should be copied to
|
|
301
|
+
// "immediate mutations". The corresponding "insert" will also be executed
|
|
302
|
+
// immediately and animated as an update.
|
|
303
|
+
std::vector<AnimationKeyFrame> keyFramesToAnimate;
|
|
304
|
+
auto const layoutAnimationConfig = animation.layoutAnimationConfig;
|
|
305
|
+
for (auto const &mutation : mutations) {
|
|
306
|
+
ShadowView baselineShadowView =
|
|
307
|
+
(mutation.type == ShadowViewMutation::Type::Delete ||
|
|
308
|
+
mutation.type == ShadowViewMutation::Type::Remove ||
|
|
309
|
+
mutation.type == ShadowViewMutation::Type::Update
|
|
310
|
+
? mutation.oldChildShadowView
|
|
311
|
+
: mutation.newChildShadowView);
|
|
312
|
+
react_native_assert(baselineShadowView.tag > 0);
|
|
313
|
+
bool haveComponentDescriptor =
|
|
314
|
+
hasComponentDescriptorForShadowView(baselineShadowView);
|
|
671
315
|
|
|
672
|
-
|
|
316
|
+
// Immediately execute any mutations on a root node
|
|
317
|
+
if (baselineShadowView.traits.check(
|
|
318
|
+
ShadowNodeTraits::Trait::RootNodeKind)) {
|
|
319
|
+
immediateMutations.push_back(mutation);
|
|
673
320
|
continue;
|
|
674
321
|
}
|
|
675
322
|
|
|
676
|
-
|
|
677
|
-
// directly; or, the parent of the node is created or deleted. In cases
|
|
678
|
-
// of reparenting - say, the parent is deleted but the node was moved to
|
|
679
|
-
// a different parent first - the reparenting (remove/insert) conflict
|
|
680
|
-
// will be detected before we process the parent DELETE.
|
|
681
|
-
// Parent deletion is important because deleting a parent recursively
|
|
682
|
-
// deletes all children. If we previously deferred deletion of a child,
|
|
683
|
-
// we need to force deletion/removal to happen immediately.
|
|
684
|
-
bool conflicting = animatedKeyFrame.tag == baselineTag ||
|
|
685
|
-
(mutationIsCreateOrDelete &&
|
|
686
|
-
animatedKeyFrame.parentView.tag == baselineTag &&
|
|
687
|
-
animatedKeyFrame.parentView.tag != 0);
|
|
688
|
-
|
|
689
|
-
// Conflicting animation detected: if we're mutating a tag under
|
|
690
|
-
// animation, or deleting the parent of a tag under animation, or
|
|
691
|
-
// reparenting.
|
|
692
|
-
if (conflicting) {
|
|
693
|
-
animatedKeyFrame.invalidated = true;
|
|
694
|
-
|
|
695
|
-
// We construct a list of all conflicting animations, whether or not
|
|
696
|
-
// they have a "final mutation" to execute. This is important with,
|
|
697
|
-
// for example, "insert" mutations where the final update needs to set
|
|
698
|
-
// opacity to "1", even if there's no final ShadowNode update.
|
|
699
|
-
// TODO: don't animate virtual views in the first place?
|
|
700
|
-
bool isVirtual = false;
|
|
701
|
-
for (const auto &finalMutationForKeyFrame :
|
|
702
|
-
animatedKeyFrame.finalMutationsForKeyFrame) {
|
|
703
|
-
isVirtual =
|
|
704
|
-
isVirtual || finalMutationForKeyFrame.mutatedViewIsVirtual();
|
|
323
|
+
better::optional<ShadowViewMutation> executeMutationImmediately{};
|
|
705
324
|
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
finalMutationForKeyFrame);
|
|
711
|
-
#endif
|
|
712
|
-
}
|
|
325
|
+
bool isRemoveReinserted =
|
|
326
|
+
mutation.type == ShadowViewMutation::Type::Remove &&
|
|
327
|
+
insertedTags.find(mutation.oldChildShadowView.tag) !=
|
|
328
|
+
insertedTags.end();
|
|
713
329
|
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
}
|
|
722
|
-
}
|
|
330
|
+
// Reparenting can result in a node being removed, inserted (moved) and
|
|
331
|
+
// also deleted and created in the same frame, with the same props etc.
|
|
332
|
+
// This should eventually be optimized out of the diffing algorithm, but
|
|
333
|
+
// for now we detect reparenting and prevent the corresponding
|
|
334
|
+
// Delete/Create instructions from being animated.
|
|
335
|
+
bool isReparented =
|
|
336
|
+
reparentedTags.find(baselineShadowView.tag) != reparentedTags.end();
|
|
723
337
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
} else {
|
|
727
|
-
it++;
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
// Recurse, in case conflicting mutations conflict with other existing
|
|
734
|
-
// animations
|
|
735
|
-
if (!localConflictingMutations.empty()) {
|
|
736
|
-
getAndEraseConflictingAnimations(
|
|
737
|
-
surfaceId, localConflictingMutations, conflictingAnimations);
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
void LayoutAnimationKeyFrameManager::setClockNow(
|
|
742
|
-
std::function<uint64_t()> now) {
|
|
743
|
-
now_ = now;
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
better::optional<MountingTransaction>
|
|
747
|
-
LayoutAnimationKeyFrameManager::pullTransaction(
|
|
748
|
-
SurfaceId surfaceId,
|
|
749
|
-
MountingTransaction::Number transactionNumber,
|
|
750
|
-
TransactionTelemetry const &telemetry,
|
|
751
|
-
ShadowViewMutationList mutations) const {
|
|
752
|
-
// Current time in milliseconds
|
|
753
|
-
uint64_t now = now_();
|
|
754
|
-
|
|
755
|
-
bool inflightAnimationsExistInitially = !inflightAnimations_.empty();
|
|
756
|
-
|
|
757
|
-
// Execute stopSurface on any ongoing animations
|
|
758
|
-
if (inflightAnimationsExistInitially) {
|
|
759
|
-
std::vector<SurfaceId> surfaceIdsToStop{};
|
|
760
|
-
{
|
|
761
|
-
std::lock_guard<std::mutex> lock(surfaceIdsToStopMutex_);
|
|
762
|
-
surfaceIdsToStop = surfaceIdsToStop_;
|
|
763
|
-
surfaceIdsToStop_ = {};
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
for (auto it = inflightAnimations_.begin();
|
|
767
|
-
it != inflightAnimations_.end();) {
|
|
768
|
-
const auto &animation = *it;
|
|
769
|
-
|
|
770
|
-
if (std::find(
|
|
771
|
-
surfaceIdsToStop.begin(),
|
|
772
|
-
surfaceIdsToStop.end(),
|
|
773
|
-
animation.surfaceId) != surfaceIdsToStop.end()) {
|
|
774
|
-
#ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
|
|
775
|
-
LOG(ERROR)
|
|
776
|
-
<< "LayoutAnimations: stopping animation due to stopSurface on "
|
|
777
|
-
<< surfaceId;
|
|
778
|
-
#endif
|
|
779
|
-
it = inflightAnimations_.erase(it);
|
|
780
|
-
} else {
|
|
781
|
-
it++;
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
if (!mutations.empty()) {
|
|
787
|
-
#ifdef RN_SHADOW_TREE_INTROSPECTION
|
|
788
|
-
{
|
|
789
|
-
std::stringstream ss(getDebugDescription(mutations, {}));
|
|
790
|
-
std::string to;
|
|
791
|
-
while (std::getline(ss, to, '\n')) {
|
|
792
|
-
LOG(ERROR)
|
|
793
|
-
<< "LayoutAnimationKeyFrameManager.cpp: got mutation list: Line: "
|
|
794
|
-
<< to;
|
|
795
|
-
}
|
|
796
|
-
};
|
|
797
|
-
#endif
|
|
798
|
-
|
|
799
|
-
// DEBUG ONLY: list existing inflight animations
|
|
800
|
-
#ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
|
|
801
|
-
LOG(ERROR) << "BEGINNING DISPLAYING ONGOING inflightAnimations_!";
|
|
802
|
-
int i = 0;
|
|
803
|
-
int j = 0;
|
|
804
|
-
for (auto const &inflightAnimation : inflightAnimations_) {
|
|
805
|
-
i++;
|
|
806
|
-
j = 0;
|
|
807
|
-
if (inflightAnimation.completed) {
|
|
808
|
-
continue;
|
|
809
|
-
}
|
|
810
|
-
for (auto &keyframe : inflightAnimation.keyFrames) {
|
|
811
|
-
j++;
|
|
812
|
-
if (keyframe.invalidated) {
|
|
813
|
-
continue;
|
|
814
|
-
}
|
|
815
|
-
for (const auto &finalMutationForKeyFrame :
|
|
816
|
-
keyframe.finalMutationsForKeyFrame) {
|
|
817
|
-
if (finalMutationForKeyFrame.mutatedViewIsVirtual()) {
|
|
818
|
-
std::string msg = "Animation " + std::to_string(i) + " keyframe " +
|
|
819
|
-
std::to_string(j) + ": Final Animation";
|
|
820
|
-
PrintMutationInstruction(msg, finalMutationForKeyFrame);
|
|
821
|
-
} else {
|
|
822
|
-
LOG(ERROR) << "Animation " << i << " keyframe " << j
|
|
823
|
-
<< ": on tag: [" << keyframe.viewStart.tag << "]";
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
LOG(ERROR) << "BEGINNING DONE DISPLAYING ONGOING inflightAnimations_!";
|
|
829
|
-
#endif
|
|
830
|
-
|
|
831
|
-
// Stub PropsParserContext used for cloneProps.
|
|
832
|
-
// This is/should be safe because cloning doesn't actually need to
|
|
833
|
-
// parse props, and just copies them; therefore there should be no
|
|
834
|
-
// need to actually use anything in the PropsParserContext.
|
|
835
|
-
// If this ever changes, the LayoutAnimations API will need to change
|
|
836
|
-
// to pass in a real PropsParserContext.
|
|
837
|
-
ContextContainer contextContainer{};
|
|
838
|
-
PropsParserContext propsParserContext{surfaceId, contextContainer};
|
|
839
|
-
|
|
840
|
-
// What to do if we detect a conflict? Get current value and make
|
|
841
|
-
// that the baseline of the next animation. Scale the remaining time
|
|
842
|
-
// in the animation
|
|
843
|
-
// Types of conflicts and how we handle them:
|
|
844
|
-
// Update -> update: remove the previous update, make it the baseline of the
|
|
845
|
-
// next update (with current progress) Update -> remove: same, with final
|
|
846
|
-
// mutation being a remove Insert -> update: treat as update->update Insert
|
|
847
|
-
// -> remove: same, as update->remove Remove -> update/insert: not possible
|
|
848
|
-
// We just collect pairs here of <Mutation, AnimationConfig> and delete them
|
|
849
|
-
// from active animations. If another animation is queued up from the
|
|
850
|
-
// current mutations then these deleted mutations will serve as the baseline
|
|
851
|
-
// for the next animation. If not, the current mutations are executed
|
|
852
|
-
// immediately without issues.
|
|
853
|
-
std::vector<AnimationKeyFrame> conflictingAnimations{};
|
|
854
|
-
getAndEraseConflictingAnimations(
|
|
855
|
-
surfaceId, mutations, conflictingAnimations);
|
|
856
|
-
|
|
857
|
-
// Are we animating this list of mutations?
|
|
858
|
-
better::optional<LayoutAnimation> currentAnimation{};
|
|
859
|
-
{
|
|
860
|
-
std::lock_guard<std::mutex> lock(currentAnimationMutex_);
|
|
861
|
-
if (currentAnimation_) {
|
|
862
|
-
currentAnimation = std::move(currentAnimation_);
|
|
863
|
-
currentAnimation_ = {};
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
if (currentAnimation) {
|
|
868
|
-
LayoutAnimation animation = std::move(currentAnimation.value());
|
|
869
|
-
currentAnimation = {};
|
|
870
|
-
animation.surfaceId = surfaceId;
|
|
871
|
-
animation.startTime = now;
|
|
872
|
-
|
|
873
|
-
// Pre-process list to:
|
|
874
|
-
// Catch remove+reinsert (reorders)
|
|
875
|
-
// Catch delete+create (reparenting) (this should be optimized away at
|
|
876
|
-
// the diffing level eventually?)
|
|
877
|
-
// TODO: to prevent this step we could tag Remove/Insert mutations as
|
|
878
|
-
// being moves on the Differ level, since we know that there? We could use
|
|
879
|
-
// TinyMap here, but it's not exposed by Differentiator (yet).
|
|
880
|
-
std::vector<Tag> insertedTags;
|
|
881
|
-
std::vector<Tag> deletedTags;
|
|
882
|
-
std::vector<Tag> reparentedTags; // tags that are deleted and recreated
|
|
883
|
-
std::unordered_map<Tag, ShadowViewMutation> movedTags;
|
|
884
|
-
for (const auto &mutation : mutations) {
|
|
885
|
-
if (mutation.type == ShadowViewMutation::Type::Insert) {
|
|
886
|
-
insertedTags.push_back(mutation.newChildShadowView.tag);
|
|
887
|
-
}
|
|
888
|
-
if (mutation.type == ShadowViewMutation::Type::Delete) {
|
|
889
|
-
deletedTags.push_back(mutation.oldChildShadowView.tag);
|
|
890
|
-
}
|
|
891
|
-
if (mutation.type == ShadowViewMutation::Type::Create) {
|
|
892
|
-
if (std::find(
|
|
893
|
-
deletedTags.begin(),
|
|
894
|
-
deletedTags.end(),
|
|
895
|
-
mutation.newChildShadowView.tag) != deletedTags.end()) {
|
|
896
|
-
reparentedTags.push_back(mutation.newChildShadowView.tag);
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
// Process mutations list into operations that can be sent to platform
|
|
902
|
-
// immediately, and those that need to be animated Deletions, removals,
|
|
903
|
-
// updates are delayed and animated. Creations and insertions are sent to
|
|
904
|
-
// platform and then "animated in" with opacity updates. Upon completion,
|
|
905
|
-
// removals and deletions are sent to platform
|
|
906
|
-
ShadowViewMutation::List immediateMutations;
|
|
907
|
-
|
|
908
|
-
// Remove operations that are actually moves should be copied to
|
|
909
|
-
// "immediate mutations". The corresponding "insert" will also be executed
|
|
910
|
-
// immediately and animated as an update.
|
|
911
|
-
std::vector<AnimationKeyFrame> keyFramesToAnimate;
|
|
912
|
-
std::vector<AnimationKeyFrame> movesToAnimate;
|
|
913
|
-
auto const layoutAnimationConfig = animation.layoutAnimationConfig;
|
|
914
|
-
for (auto const &mutation : mutations) {
|
|
915
|
-
ShadowView baselineShadowView =
|
|
916
|
-
(mutation.type == ShadowViewMutation::Type::Delete ||
|
|
917
|
-
mutation.type == ShadowViewMutation::Type::Remove ||
|
|
918
|
-
mutation.type == ShadowViewMutation::Type::Update
|
|
919
|
-
? mutation.oldChildShadowView
|
|
920
|
-
: mutation.newChildShadowView);
|
|
921
|
-
react_native_assert(baselineShadowView.tag > 0);
|
|
922
|
-
bool haveComponentDescriptor =
|
|
923
|
-
hasComponentDescriptorForShadowView(baselineShadowView);
|
|
924
|
-
|
|
925
|
-
// Immediately execute any mutations on a root node
|
|
926
|
-
if (baselineShadowView.traits.check(
|
|
927
|
-
ShadowNodeTraits::Trait::RootNodeKind)) {
|
|
928
|
-
immediateMutations.push_back(mutation);
|
|
929
|
-
continue;
|
|
930
|
-
}
|
|
931
|
-
|
|
932
|
-
better::optional<ShadowViewMutation> executeMutationImmediately{};
|
|
933
|
-
|
|
934
|
-
bool isRemoveReinserted =
|
|
935
|
-
mutation.type == ShadowViewMutation::Type::Remove &&
|
|
936
|
-
std::find(
|
|
937
|
-
insertedTags.begin(),
|
|
938
|
-
insertedTags.end(),
|
|
939
|
-
mutation.oldChildShadowView.tag) != insertedTags.end();
|
|
940
|
-
|
|
941
|
-
// Reparenting can result in a node being removed, inserted (moved) and
|
|
942
|
-
// also deleted and created in the same frame, with the same props etc.
|
|
943
|
-
// This should eventually be optimized out of the diffing algorithm, but
|
|
944
|
-
// for now we detect reparenting and prevent the corresponding
|
|
945
|
-
// Delete/Create instructions from being animated.
|
|
946
|
-
bool isReparented = std::find(
|
|
947
|
-
reparentedTags.begin(),
|
|
948
|
-
reparentedTags.end(),
|
|
949
|
-
baselineShadowView.tag) != reparentedTags.end();
|
|
950
|
-
|
|
951
|
-
if (isRemoveReinserted) {
|
|
952
|
-
movedTags.insert({mutation.oldChildShadowView.tag, mutation});
|
|
338
|
+
if (isRemoveReinserted) {
|
|
339
|
+
movedTags.insert({mutation.oldChildShadowView.tag, mutation});
|
|
953
340
|
}
|
|
954
341
|
|
|
955
342
|
// Inserts that follow a "remove" of the same tag should be treated as
|
|
@@ -979,16 +366,6 @@ LayoutAnimationKeyFrameManager::pullTransaction(
|
|
|
979
366
|
bool haveConfiguration =
|
|
980
367
|
mutationConfig.animationType != AnimationType::None;
|
|
981
368
|
|
|
982
|
-
if (wasInsertedTagRemoved && haveConfiguration) {
|
|
983
|
-
movesToAnimate.push_back(AnimationKeyFrame{
|
|
984
|
-
{},
|
|
985
|
-
AnimationConfigurationType::Update,
|
|
986
|
-
mutation.newChildShadowView.tag,
|
|
987
|
-
mutation.parentShadowView,
|
|
988
|
-
movedIt->second.oldChildShadowView,
|
|
989
|
-
mutation.newChildShadowView});
|
|
990
|
-
}
|
|
991
|
-
|
|
992
369
|
// Creates and inserts should also be executed immediately.
|
|
993
370
|
// Mutations that would otherwise be animated, but have no
|
|
994
371
|
// configuration, are also executed immediately.
|
|
@@ -1051,12 +428,11 @@ LayoutAnimationKeyFrameManager::pullTransaction(
|
|
|
1051
428
|
// that is being referenced by the REMOVE mutation.
|
|
1052
429
|
if (keyframe.type == AnimationConfigurationType::Update &&
|
|
1053
430
|
mutation.oldChildShadowView.tag > 0) {
|
|
1054
|
-
executeMutationImmediately =
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
mutation.index};
|
|
431
|
+
executeMutationImmediately =
|
|
432
|
+
ShadowViewMutation::RemoveMutation(
|
|
433
|
+
mutation.parentShadowView,
|
|
434
|
+
keyframe.viewPrev,
|
|
435
|
+
mutation.index);
|
|
1060
436
|
}
|
|
1061
437
|
}
|
|
1062
438
|
}
|
|
@@ -1093,13 +469,11 @@ LayoutAnimationKeyFrameManager::pullTransaction(
|
|
|
1093
469
|
getComponentDescriptorForShadowView(baselineShadowView)
|
|
1094
470
|
.cloneProps(propsParserContext, viewStart.props, {});
|
|
1095
471
|
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
if (viewProps != nullptr) {
|
|
1102
|
-
const_cast<ViewProps *>(viewProps)->opacity = 0;
|
|
472
|
+
if (baselineShadowView.traits.check(
|
|
473
|
+
ShadowNodeTraits::Trait::ViewKind)) {
|
|
474
|
+
auto const &viewProps =
|
|
475
|
+
*std::static_pointer_cast<ViewProps const>(props);
|
|
476
|
+
const_cast<ViewProps &>(viewProps).opacity = 0;
|
|
1103
477
|
}
|
|
1104
478
|
|
|
1105
479
|
react_native_assert(props != nullptr);
|
|
@@ -1117,14 +491,11 @@ LayoutAnimationKeyFrameManager::pullTransaction(
|
|
|
1117
491
|
auto props =
|
|
1118
492
|
getComponentDescriptorForShadowView(baselineShadowView)
|
|
1119
493
|
.cloneProps(propsParserContext, viewStart.props, {});
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
dynamic_cast<const ViewProps *>(props.get());
|
|
1126
|
-
if (viewProps != nullptr) {
|
|
1127
|
-
const_cast<ViewProps *>(viewProps)->transform =
|
|
494
|
+
if (baselineShadowView.traits.check(
|
|
495
|
+
ShadowNodeTraits::Trait::ViewKind)) {
|
|
496
|
+
auto const &viewProps =
|
|
497
|
+
*std::static_pointer_cast<ViewProps const>(props);
|
|
498
|
+
const_cast<ViewProps &>(viewProps).transform =
|
|
1128
499
|
Transform::Scale(isScaleX ? 0 : 1, isScaleY ? 0 : 1, 1);
|
|
1129
500
|
}
|
|
1130
501
|
|
|
@@ -1139,14 +510,14 @@ LayoutAnimationKeyFrameManager::pullTransaction(
|
|
|
1139
510
|
mutation);
|
|
1140
511
|
|
|
1141
512
|
keyFrame = AnimationKeyFrame{
|
|
1142
|
-
{},
|
|
1143
|
-
AnimationConfigurationType::Create,
|
|
1144
|
-
tag,
|
|
1145
|
-
parent,
|
|
1146
|
-
viewStart,
|
|
1147
|
-
viewFinal,
|
|
1148
|
-
baselineShadowView,
|
|
1149
|
-
0};
|
|
513
|
+
/* .finalMutationsForKeyFrame = */ {},
|
|
514
|
+
/* .type = */ AnimationConfigurationType::Create,
|
|
515
|
+
/* .tag = */ tag,
|
|
516
|
+
/* .parentView = */ parent,
|
|
517
|
+
/* .viewStart = */ viewStart,
|
|
518
|
+
/* .viewEnd = */ viewFinal,
|
|
519
|
+
/* .viewPrev = */ baselineShadowView,
|
|
520
|
+
/* .initialProgress = */ 0};
|
|
1150
521
|
} else if (mutation.type == ShadowViewMutation::Type::Delete) {
|
|
1151
522
|
// This is just for assertion purposes.
|
|
1152
523
|
// The NDEBUG check here is to satisfy the compiler in certain environments
|
|
@@ -1177,14 +548,14 @@ LayoutAnimationKeyFrameManager::pullTransaction(
|
|
|
1177
548
|
mutation);
|
|
1178
549
|
|
|
1179
550
|
keyFrame = AnimationKeyFrame{
|
|
1180
|
-
{mutation},
|
|
1181
|
-
AnimationConfigurationType::Update,
|
|
1182
|
-
tag,
|
|
1183
|
-
parent,
|
|
1184
|
-
viewStart,
|
|
1185
|
-
viewFinal,
|
|
1186
|
-
baselineShadowView,
|
|
1187
|
-
0};
|
|
551
|
+
/* .finalMutationsForKeyFrame = */ {mutation},
|
|
552
|
+
/* .type = */ AnimationConfigurationType::Update,
|
|
553
|
+
/* .tag = */ tag,
|
|
554
|
+
/* .parentView = */ parent,
|
|
555
|
+
/* .viewStart = */ viewStart,
|
|
556
|
+
/* .viewEnd = */ viewFinal,
|
|
557
|
+
/* .viewPrev = */ baselineShadowView,
|
|
558
|
+
/* .initialProgress = */ 0};
|
|
1188
559
|
} else {
|
|
1189
560
|
// This should just be "Remove" instructions that are not animated
|
|
1190
561
|
// (either this is a "move", or there's a corresponding "Delete"
|
|
@@ -1221,13 +592,11 @@ LayoutAnimationKeyFrameManager::pullTransaction(
|
|
|
1221
592
|
getComponentDescriptorForShadowView(baselineShadowView)
|
|
1222
593
|
.cloneProps(propsParserContext, viewFinal.props, {});
|
|
1223
594
|
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
if (viewProps != nullptr) {
|
|
1230
|
-
const_cast<ViewProps *>(viewProps)->opacity = 0;
|
|
595
|
+
if (baselineShadowView.traits.check(
|
|
596
|
+
ShadowNodeTraits::Trait::ViewKind)) {
|
|
597
|
+
auto const &viewProps =
|
|
598
|
+
*std::static_pointer_cast<ViewProps const>(props);
|
|
599
|
+
const_cast<ViewProps &>(viewProps).opacity = 0;
|
|
1231
600
|
}
|
|
1232
601
|
|
|
1233
602
|
react_native_assert(props != nullptr);
|
|
@@ -1248,13 +617,11 @@ LayoutAnimationKeyFrameManager::pullTransaction(
|
|
|
1248
617
|
getComponentDescriptorForShadowView(baselineShadowView)
|
|
1249
618
|
.cloneProps(propsParserContext, viewFinal.props, {});
|
|
1250
619
|
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
if (viewProps != nullptr) {
|
|
1257
|
-
const_cast<ViewProps *>(viewProps)->transform =
|
|
620
|
+
if (baselineShadowView.traits.check(
|
|
621
|
+
ShadowNodeTraits::Trait::ViewKind)) {
|
|
622
|
+
auto const &viewProps =
|
|
623
|
+
*std::static_pointer_cast<ViewProps const>(props);
|
|
624
|
+
const_cast<ViewProps &>(viewProps).transform =
|
|
1258
625
|
Transform::Scale(isScaleX ? 0 : 1, isScaleY ? 0 : 1, 1);
|
|
1259
626
|
}
|
|
1260
627
|
|
|
@@ -1269,14 +636,14 @@ LayoutAnimationKeyFrameManager::pullTransaction(
|
|
|
1269
636
|
mutation);
|
|
1270
637
|
|
|
1271
638
|
keyFrame = AnimationKeyFrame{
|
|
1272
|
-
{mutation, deleteMutation},
|
|
1273
|
-
AnimationConfigurationType::Delete,
|
|
1274
|
-
tag,
|
|
1275
|
-
parent,
|
|
1276
|
-
viewStart,
|
|
1277
|
-
viewFinal,
|
|
1278
|
-
baselineShadowView,
|
|
1279
|
-
0};
|
|
639
|
+
/* .finalMutationsForKeyFrame */ {mutation, deleteMutation},
|
|
640
|
+
/* .type */ AnimationConfigurationType::Delete,
|
|
641
|
+
/* .tag */ tag,
|
|
642
|
+
/* .parentView */ parent,
|
|
643
|
+
/* .viewStart */ viewStart,
|
|
644
|
+
/* .viewEnd */ viewFinal,
|
|
645
|
+
/* .viewPrev */ baselineShadowView,
|
|
646
|
+
/* .initialProgress */ 0};
|
|
1280
647
|
} else {
|
|
1281
648
|
PrintMutationInstruction(
|
|
1282
649
|
"Executing Remove Immediately, due to reordering operation",
|
|
@@ -1415,7 +782,7 @@ LayoutAnimationKeyFrameManager::pullTransaction(
|
|
|
1415
782
|
// don't want to queue up any final UPDATE mutations here.
|
|
1416
783
|
bool shouldGenerateSyntheticMutations =
|
|
1417
784
|
keyFrame.generateFinalSyntheticMutations;
|
|
1418
|
-
|
|
785
|
+
auto numFinalMutations = keyFrame.finalMutationsForKeyFrame.size();
|
|
1419
786
|
bool onlyMutationIsUpdate =
|
|
1420
787
|
(numFinalMutations == 1 &&
|
|
1421
788
|
keyFrame.finalMutationsForKeyFrame[0].type ==
|
|
@@ -1575,340 +942,738 @@ LayoutAnimationKeyFrameManager::pullTransaction(
|
|
|
1575
942
|
"Conflict with non-animated mutation");
|
|
1576
943
|
}
|
|
1577
944
|
|
|
1578
|
-
// Make sure that all operations execute in the proper order.
|
|
1579
|
-
// REMOVE operations with highest indices must operate first.
|
|
1580
|
-
std::stable_sort(
|
|
1581
|
-
finalMutationsForConflictingAnimations.begin(),
|
|
1582
|
-
finalMutationsForConflictingAnimations.end(),
|
|
1583
|
-
&shouldFirstComeBeforeSecondMutation);
|
|
945
|
+
// Make sure that all operations execute in the proper order.
|
|
946
|
+
// REMOVE operations with highest indices must operate first.
|
|
947
|
+
std::stable_sort(
|
|
948
|
+
finalMutationsForConflictingAnimations.begin(),
|
|
949
|
+
finalMutationsForConflictingAnimations.end(),
|
|
950
|
+
&shouldFirstComeBeforeSecondMutation);
|
|
951
|
+
|
|
952
|
+
#ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
|
|
953
|
+
LOG(ERROR)
|
|
954
|
+
<< "No Animation: Adjust delayed mutations based on all finalMutationsForConflictingAnimations";
|
|
955
|
+
#endif
|
|
956
|
+
for (auto const &mutation : finalMutationsForConflictingAnimations) {
|
|
957
|
+
if (mutation.type == ShadowViewMutation::Type::Remove ||
|
|
958
|
+
mutation.type == ShadowViewMutation::Type::Insert) {
|
|
959
|
+
adjustDelayedMutationIndicesForMutation(surfaceId, mutation);
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
// The ShadowTree layer doesn't realize that certain operations have
|
|
964
|
+
// been delayed, so we must adjust all Remove and Insert operations
|
|
965
|
+
// based on what else has been deferred, whether we are executing this
|
|
966
|
+
// immediately or later.
|
|
967
|
+
#ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
|
|
968
|
+
LOG(ERROR)
|
|
969
|
+
<< "No Animation: Adjust mutations based on remaining delayed mutations / adjust delayed, based on each";
|
|
970
|
+
#endif
|
|
971
|
+
for (auto &mutation : mutations) {
|
|
972
|
+
if (mutation.type == ShadowViewMutation::Type::Remove ||
|
|
973
|
+
mutation.type == ShadowViewMutation::Type::Insert) {
|
|
974
|
+
adjustImmediateMutationIndicesForDelayedMutations(
|
|
975
|
+
surfaceId, mutation);
|
|
976
|
+
adjustDelayedMutationIndicesForMutation(surfaceId, mutation);
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
// Append mutations to this list and swap - so that the final
|
|
981
|
+
// conflicting mutations happen before any other mutations
|
|
982
|
+
finalMutationsForConflictingAnimations.insert(
|
|
983
|
+
finalMutationsForConflictingAnimations.end(),
|
|
984
|
+
mutations.begin(),
|
|
985
|
+
mutations.end());
|
|
986
|
+
mutations = finalMutationsForConflictingAnimations;
|
|
987
|
+
}
|
|
988
|
+
} // if (mutations)
|
|
989
|
+
|
|
990
|
+
// We never commit a different root or modify anything -
|
|
991
|
+
// we just send additional mutations to the mounting layer until the
|
|
992
|
+
// animations are finished and the mounting layer (view) represents exactly
|
|
993
|
+
// what is in the most recent shadow tree
|
|
994
|
+
// Add animation mutations to the end of our existing mutations list in this
|
|
995
|
+
// function.
|
|
996
|
+
ShadowViewMutationList mutationsForAnimation{};
|
|
997
|
+
animationMutationsForFrame(surfaceId, mutationsForAnimation, now);
|
|
998
|
+
|
|
999
|
+
// If any delayed removes were executed, update remaining delayed keyframes
|
|
1000
|
+
#ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
|
|
1001
|
+
LOG(ERROR)
|
|
1002
|
+
<< "Adjust all delayed mutations based on final mutations generated by animation driver";
|
|
1003
|
+
#endif
|
|
1004
|
+
for (auto const &mutation : mutationsForAnimation) {
|
|
1005
|
+
if (mutation.type == ShadowViewMutation::Type::Remove) {
|
|
1006
|
+
adjustDelayedMutationIndicesForMutation(surfaceId, mutation);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
mutations.insert(
|
|
1011
|
+
mutations.end(),
|
|
1012
|
+
mutationsForAnimation.begin(),
|
|
1013
|
+
mutationsForAnimation.end());
|
|
1014
|
+
|
|
1015
|
+
// DEBUG ONLY: list existing inflight animations
|
|
1016
|
+
#ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
|
|
1017
|
+
LOG(ERROR) << "FINISHING DISPLAYING ONGOING inflightAnimations_!";
|
|
1018
|
+
int i = 0;
|
|
1019
|
+
int j = 0;
|
|
1020
|
+
for (auto const &inflightAnimation : inflightAnimations_) {
|
|
1021
|
+
i++;
|
|
1022
|
+
j = 0;
|
|
1023
|
+
if (inflightAnimation.completed) {
|
|
1024
|
+
continue;
|
|
1025
|
+
}
|
|
1026
|
+
for (auto &keyframe : inflightAnimation.keyFrames) {
|
|
1027
|
+
j++;
|
|
1028
|
+
if (keyframe.invalidated) {
|
|
1029
|
+
continue;
|
|
1030
|
+
}
|
|
1031
|
+
for (auto const &finalMutation : keyframe.finalMutationsForKeyFrame) {
|
|
1032
|
+
if (!finalMutation.mutatedViewIsVirtual()) {
|
|
1033
|
+
std::string msg = "Animation " + std::to_string(i) + " keyframe " +
|
|
1034
|
+
std::to_string(j) + ": Final Animation";
|
|
1035
|
+
PrintMutationInstruction(msg, finalMutation);
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
LOG(ERROR) << "FINISHING DONE DISPLAYING ONGOING inflightAnimations_!";
|
|
1041
|
+
#endif
|
|
1042
|
+
|
|
1043
|
+
// Signal to delegate if all animations are complete, or if we were not
|
|
1044
|
+
// animating anything and now some animation exists.
|
|
1045
|
+
if (inflightAnimationsExistInitially && inflightAnimations_.empty()) {
|
|
1046
|
+
std::lock_guard<std::mutex> lock(layoutAnimationStatusDelegateMutex_);
|
|
1047
|
+
if (layoutAnimationStatusDelegate_ != nullptr) {
|
|
1048
|
+
layoutAnimationStatusDelegate_->onAllAnimationsComplete();
|
|
1049
|
+
}
|
|
1050
|
+
} else if (
|
|
1051
|
+
!inflightAnimationsExistInitially && !inflightAnimations_.empty()) {
|
|
1052
|
+
std::lock_guard<std::mutex> lock(layoutAnimationStatusDelegateMutex_);
|
|
1053
|
+
if (layoutAnimationStatusDelegate_ != nullptr) {
|
|
1054
|
+
layoutAnimationStatusDelegate_->onAnimationStarted();
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
simulateImagePropsMemoryAccess(mutations);
|
|
1059
|
+
|
|
1060
|
+
return MountingTransaction{
|
|
1061
|
+
surfaceId, transactionNumber, std::move(mutations), telemetry};
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
void LayoutAnimationKeyFrameManager::uiManagerDidConfigureNextLayoutAnimation(
|
|
1065
|
+
LayoutAnimation layoutAnimation) const {
|
|
1066
|
+
currentAnimation_ = better::optional<LayoutAnimation>{layoutAnimation};
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
void LayoutAnimationKeyFrameManager::setLayoutAnimationStatusDelegate(
|
|
1070
|
+
LayoutAnimationStatusDelegate *delegate) const {
|
|
1071
|
+
std::lock_guard<std::mutex> lock(layoutAnimationStatusDelegateMutex_);
|
|
1072
|
+
layoutAnimationStatusDelegate_ = delegate;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
void LayoutAnimationKeyFrameManager::setClockNow(
|
|
1076
|
+
std::function<uint64_t()> now) {
|
|
1077
|
+
now_ = now;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
void LayoutAnimationKeyFrameManager::enableSkipInvalidatedKeyFrames() {
|
|
1081
|
+
skipInvalidatedKeyFrames_ = true;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
void LayoutAnimationKeyFrameManager::enableCrashOnMissingComponentDescriptor() {
|
|
1085
|
+
crashOnMissingComponentDescriptor_ = true;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
void LayoutAnimationKeyFrameManager::enableSimulateImagePropsMemoryAccess() {
|
|
1089
|
+
simulateImagePropsMemoryAccess_ = true;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
#pragma mark - Protected
|
|
1093
|
+
|
|
1094
|
+
bool LayoutAnimationKeyFrameManager::hasComponentDescriptorForShadowView(
|
|
1095
|
+
ShadowView const &shadowView) const {
|
|
1096
|
+
auto hasComponentDescriptor =
|
|
1097
|
+
componentDescriptorRegistry_->hasComponentDescriptorAt(
|
|
1098
|
+
shadowView.componentHandle);
|
|
1099
|
+
|
|
1100
|
+
if (crashOnMissingComponentDescriptor_ && !hasComponentDescriptor) {
|
|
1101
|
+
LOG(FATAL) << "Component descriptor with handle: "
|
|
1102
|
+
<< shadowView.componentHandle
|
|
1103
|
+
<< " doesn't exist. The component name: "
|
|
1104
|
+
<< shadowView.componentName;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
return hasComponentDescriptor;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
ComponentDescriptor const &
|
|
1111
|
+
LayoutAnimationKeyFrameManager::getComponentDescriptorForShadowView(
|
|
1112
|
+
ShadowView const &shadowView) const {
|
|
1113
|
+
return componentDescriptorRegistry_->at(shadowView.componentHandle);
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
ShadowView LayoutAnimationKeyFrameManager::createInterpolatedShadowView(
|
|
1117
|
+
double progress,
|
|
1118
|
+
ShadowView const &startingView,
|
|
1119
|
+
ShadowView const &finalView) const {
|
|
1120
|
+
react_native_assert(startingView.tag > 0);
|
|
1121
|
+
react_native_assert(finalView.tag > 0);
|
|
1122
|
+
if (!hasComponentDescriptorForShadowView(startingView)) {
|
|
1123
|
+
LOG(ERROR) << "No ComponentDescriptor for ShadowView being animated: ["
|
|
1124
|
+
<< startingView.tag << "]";
|
|
1125
|
+
react_native_assert(false);
|
|
1126
|
+
return finalView;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
ComponentDescriptor const &componentDescriptor =
|
|
1130
|
+
getComponentDescriptorForShadowView(startingView);
|
|
1131
|
+
|
|
1132
|
+
// Base the mutated view on the finalView, so that the following stay
|
|
1133
|
+
// consistent:
|
|
1134
|
+
// - state
|
|
1135
|
+
// - eventEmitter
|
|
1136
|
+
// For now, we do not allow interpolation of state. And we probably never
|
|
1137
|
+
// will, so make sure we always keep the mounting layer consistent with the
|
|
1138
|
+
// "final" state.
|
|
1139
|
+
auto mutatedShadowView = ShadowView(finalView);
|
|
1140
|
+
react_native_assert(mutatedShadowView.tag > 0);
|
|
1141
|
+
|
|
1142
|
+
react_native_assert(startingView.props != nullptr);
|
|
1143
|
+
react_native_assert(finalView.props != nullptr);
|
|
1144
|
+
if (startingView.props == nullptr || finalView.props == nullptr) {
|
|
1145
|
+
return finalView;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
// Animate opacity or scale/transform
|
|
1149
|
+
PropsParserContext propsParserContext{
|
|
1150
|
+
finalView.surfaceId, *contextContainer_};
|
|
1151
|
+
mutatedShadowView.props = componentDescriptor.interpolateProps(
|
|
1152
|
+
propsParserContext, progress, startingView.props, finalView.props);
|
|
1153
|
+
react_native_assert(mutatedShadowView.props != nullptr);
|
|
1154
|
+
if (mutatedShadowView.props == nullptr) {
|
|
1155
|
+
return finalView;
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
// Interpolate LayoutMetrics
|
|
1159
|
+
LayoutMetrics const &finalLayoutMetrics = finalView.layoutMetrics;
|
|
1160
|
+
LayoutMetrics const &baselineLayoutMetrics = startingView.layoutMetrics;
|
|
1161
|
+
LayoutMetrics interpolatedLayoutMetrics = finalLayoutMetrics;
|
|
1162
|
+
interpolatedLayoutMetrics.frame.origin.x = interpolateFloats(
|
|
1163
|
+
progress,
|
|
1164
|
+
baselineLayoutMetrics.frame.origin.x,
|
|
1165
|
+
finalLayoutMetrics.frame.origin.x);
|
|
1166
|
+
interpolatedLayoutMetrics.frame.origin.y = interpolateFloats(
|
|
1167
|
+
progress,
|
|
1168
|
+
baselineLayoutMetrics.frame.origin.y,
|
|
1169
|
+
finalLayoutMetrics.frame.origin.y);
|
|
1170
|
+
interpolatedLayoutMetrics.frame.size.width = interpolateFloats(
|
|
1171
|
+
progress,
|
|
1172
|
+
baselineLayoutMetrics.frame.size.width,
|
|
1173
|
+
finalLayoutMetrics.frame.size.width);
|
|
1174
|
+
interpolatedLayoutMetrics.frame.size.height = interpolateFloats(
|
|
1175
|
+
progress,
|
|
1176
|
+
baselineLayoutMetrics.frame.size.height,
|
|
1177
|
+
finalLayoutMetrics.frame.size.height);
|
|
1178
|
+
mutatedShadowView.layoutMetrics = interpolatedLayoutMetrics;
|
|
1179
|
+
|
|
1180
|
+
return mutatedShadowView;
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
void LayoutAnimationKeyFrameManager::callCallback(
|
|
1184
|
+
LayoutAnimationCallbackWrapper const &callback) const {
|
|
1185
|
+
runtimeExecutor_(
|
|
1186
|
+
[callback](jsi::Runtime &runtime) { callback.call(runtime); });
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
void LayoutAnimationKeyFrameManager::queueFinalMutationsForCompletedKeyFrame(
|
|
1190
|
+
AnimationKeyFrame const &keyframe,
|
|
1191
|
+
ShadowViewMutation::List &mutationsList,
|
|
1192
|
+
bool interrupted,
|
|
1193
|
+
const std::string &logPrefix) const {
|
|
1194
|
+
if (skipInvalidatedKeyFrames_ && keyframe.invalidated) {
|
|
1195
|
+
return;
|
|
1196
|
+
}
|
|
1197
|
+
if (keyframe.finalMutationsForKeyFrame.size() > 0) {
|
|
1198
|
+
// TODO: modularize this segment, it is repeated 2x in KeyFrameManager
|
|
1199
|
+
// as well.
|
|
1200
|
+
ShadowView prev = keyframe.viewPrev;
|
|
1201
|
+
for (auto const &finalMutation : keyframe.finalMutationsForKeyFrame) {
|
|
1202
|
+
PrintMutationInstruction(
|
|
1203
|
+
logPrefix + ": Queuing up Final Mutation:", finalMutation);
|
|
1204
|
+
// Copy so that if something else mutates the inflight animations,
|
|
1205
|
+
// it won't change this mutation after this point.
|
|
1206
|
+
switch (finalMutation.type) {
|
|
1207
|
+
// For CREATE/INSERT this will contain CREATE, INSERT in that order.
|
|
1208
|
+
// For REMOVE/DELETE, same.
|
|
1209
|
+
case ShadowViewMutation::Type::Create:
|
|
1210
|
+
mutationsList.push_back(ShadowViewMutation::CreateMutation(
|
|
1211
|
+
finalMutation.newChildShadowView));
|
|
1212
|
+
break;
|
|
1213
|
+
case ShadowViewMutation::Type::Delete:
|
|
1214
|
+
mutationsList.push_back(ShadowViewMutation::DeleteMutation(prev));
|
|
1215
|
+
break;
|
|
1216
|
+
case ShadowViewMutation::Type::Insert:
|
|
1217
|
+
mutationsList.push_back(ShadowViewMutation::InsertMutation(
|
|
1218
|
+
finalMutation.parentShadowView,
|
|
1219
|
+
finalMutation.newChildShadowView,
|
|
1220
|
+
finalMutation.index));
|
|
1221
|
+
break;
|
|
1222
|
+
case ShadowViewMutation::Type::Remove:
|
|
1223
|
+
mutationsList.push_back(ShadowViewMutation::RemoveMutation(
|
|
1224
|
+
finalMutation.parentShadowView, prev, finalMutation.index));
|
|
1225
|
+
break;
|
|
1226
|
+
case ShadowViewMutation::Type::Update:
|
|
1227
|
+
mutationsList.push_back(ShadowViewMutation::UpdateMutation(
|
|
1228
|
+
prev, finalMutation.newChildShadowView));
|
|
1229
|
+
break;
|
|
1230
|
+
}
|
|
1231
|
+
if (finalMutation.newChildShadowView.tag > 0) {
|
|
1232
|
+
prev = finalMutation.newChildShadowView;
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
} else {
|
|
1236
|
+
// If there's no final mutation associated, create a mutation that
|
|
1237
|
+
// corresponds to the animation being 100% complete. This is
|
|
1238
|
+
// important for, for example, INSERT mutations being animated from
|
|
1239
|
+
// opacity 0 to 1. If the animation is interrupted we must force the
|
|
1240
|
+
// View to be at opacity 1. For Android - since it passes along only
|
|
1241
|
+
// deltas, not an entire bag of props - generate an "animation"
|
|
1242
|
+
// frame corresponding to a final update for this view. Only then,
|
|
1243
|
+
// generate an update that will cause the ShadowTree to be
|
|
1244
|
+
// consistent with the Mounting layer by passing viewEnd,
|
|
1245
|
+
// unmodified, to the mounting layer. This helps with, for example,
|
|
1246
|
+
// opacity animations.
|
|
1247
|
+
// This is necessary for INSERT (create) and UPDATE (update) mutations, but
|
|
1248
|
+
// not REMOVE/DELETE mutations ("delete" animations).
|
|
1249
|
+
if (interrupted) {
|
|
1250
|
+
auto mutatedShadowView =
|
|
1251
|
+
createInterpolatedShadowView(1, keyframe.viewStart, keyframe.viewEnd);
|
|
1252
|
+
auto generatedPenultimateMutation = ShadowViewMutation::UpdateMutation(
|
|
1253
|
+
keyframe.viewPrev, mutatedShadowView);
|
|
1254
|
+
react_native_assert(
|
|
1255
|
+
generatedPenultimateMutation.oldChildShadowView.tag > 0);
|
|
1256
|
+
react_native_assert(
|
|
1257
|
+
generatedPenultimateMutation.newChildShadowView.tag > 0);
|
|
1258
|
+
PrintMutationInstruction(
|
|
1259
|
+
"Queueing up penultimate mutation instruction - synthetic",
|
|
1260
|
+
generatedPenultimateMutation);
|
|
1261
|
+
mutationsList.push_back(generatedPenultimateMutation);
|
|
1262
|
+
|
|
1263
|
+
auto generatedMutation = ShadowViewMutation::UpdateMutation(
|
|
1264
|
+
mutatedShadowView, keyframe.viewEnd);
|
|
1265
|
+
react_native_assert(generatedMutation.oldChildShadowView.tag > 0);
|
|
1266
|
+
react_native_assert(generatedMutation.newChildShadowView.tag > 0);
|
|
1267
|
+
PrintMutationInstruction(
|
|
1268
|
+
"Queueing up final mutation instruction - synthetic",
|
|
1269
|
+
generatedMutation);
|
|
1270
|
+
mutationsList.push_back(generatedMutation);
|
|
1271
|
+
} else {
|
|
1272
|
+
auto mutation = ShadowViewMutation::UpdateMutation(
|
|
1273
|
+
keyframe.viewPrev, keyframe.viewEnd);
|
|
1274
|
+
PrintMutationInstruction(
|
|
1275
|
+
logPrefix +
|
|
1276
|
+
"Animation Complete: Queuing up Final Synthetic Mutation:",
|
|
1277
|
+
mutation);
|
|
1278
|
+
react_native_assert(mutation.oldChildShadowView.tag > 0);
|
|
1279
|
+
react_native_assert(mutation.newChildShadowView.tag > 0);
|
|
1280
|
+
mutationsList.push_back(std::move(mutation));
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
#pragma mark - Private
|
|
1286
|
+
|
|
1287
|
+
void LayoutAnimationKeyFrameManager::
|
|
1288
|
+
adjustImmediateMutationIndicesForDelayedMutations(
|
|
1289
|
+
SurfaceId surfaceId,
|
|
1290
|
+
ShadowViewMutation &mutation,
|
|
1291
|
+
bool skipLastAnimation,
|
|
1292
|
+
bool lastAnimationOnly) const {
|
|
1293
|
+
bool isRemoveMutation = mutation.type == ShadowViewMutation::Type::Remove;
|
|
1294
|
+
react_native_assert(
|
|
1295
|
+
isRemoveMutation || mutation.type == ShadowViewMutation::Type::Insert);
|
|
1296
|
+
|
|
1297
|
+
// TODO: turn all of this into a lambda and share code?
|
|
1298
|
+
if (mutation.mutatedViewIsVirtual()) {
|
|
1299
|
+
PrintMutationInstruction(
|
|
1300
|
+
"[IndexAdjustment] Not calling adjustImmediateMutationIndicesForDelayedMutations, is virtual, for:",
|
|
1301
|
+
mutation);
|
|
1302
|
+
return;
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
PrintMutationInstruction(
|
|
1306
|
+
"[IndexAdjustment] Calling adjustImmediateMutationIndicesForDelayedMutations for:",
|
|
1307
|
+
mutation);
|
|
1308
|
+
|
|
1309
|
+
// First, collect all final mutations that could impact this immediate
|
|
1310
|
+
// mutation.
|
|
1311
|
+
std::vector<ShadowViewMutation *> candidateMutations{};
|
|
1312
|
+
|
|
1313
|
+
for (auto inflightAnimationIt =
|
|
1314
|
+
inflightAnimations_.rbegin() + (skipLastAnimation ? 1 : 0);
|
|
1315
|
+
inflightAnimationIt != inflightAnimations_.rend();
|
|
1316
|
+
inflightAnimationIt++) {
|
|
1317
|
+
auto &inflightAnimation = *inflightAnimationIt;
|
|
1318
|
+
if (inflightAnimation.surfaceId != surfaceId) {
|
|
1319
|
+
continue;
|
|
1320
|
+
}
|
|
1321
|
+
if (inflightAnimation.completed) {
|
|
1322
|
+
continue;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
for (auto it = inflightAnimation.keyFrames.begin();
|
|
1326
|
+
it != inflightAnimation.keyFrames.end();
|
|
1327
|
+
it++) {
|
|
1328
|
+
auto &animatedKeyFrame = *it;
|
|
1329
|
+
|
|
1330
|
+
if (animatedKeyFrame.invalidated) {
|
|
1331
|
+
continue;
|
|
1332
|
+
}
|
|
1584
1333
|
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
for (auto const &mutation : finalMutationsForConflictingAnimations) {
|
|
1590
|
-
if (mutation.type == ShadowViewMutation::Type::Remove ||
|
|
1591
|
-
mutation.type == ShadowViewMutation::Type::Insert) {
|
|
1592
|
-
adjustDelayedMutationIndicesForMutation(surfaceId, mutation);
|
|
1593
|
-
}
|
|
1334
|
+
// Detect if they're in the same view hierarchy, but not equivalent
|
|
1335
|
+
// We've already detected direct conflicts and removed them.
|
|
1336
|
+
if (animatedKeyFrame.parentView.tag != mutation.parentShadowView.tag) {
|
|
1337
|
+
continue;
|
|
1594
1338
|
}
|
|
1595
1339
|
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
adjustImmediateMutationIndicesForDelayedMutations(
|
|
1608
|
-
surfaceId, mutation);
|
|
1609
|
-
adjustDelayedMutationIndicesForMutation(surfaceId, mutation);
|
|
1340
|
+
for (auto &delayedMutation : animatedKeyFrame.finalMutationsForKeyFrame) {
|
|
1341
|
+
if (delayedMutation.type != ShadowViewMutation::Type::Remove) {
|
|
1342
|
+
continue;
|
|
1343
|
+
}
|
|
1344
|
+
if (delayedMutation.mutatedViewIsVirtual()) {
|
|
1345
|
+
continue;
|
|
1346
|
+
}
|
|
1347
|
+
if (delayedMutation.oldChildShadowView.tag ==
|
|
1348
|
+
(isRemoveMutation ? mutation.oldChildShadowView.tag
|
|
1349
|
+
: mutation.newChildShadowView.tag)) {
|
|
1350
|
+
continue;
|
|
1610
1351
|
}
|
|
1352
|
+
|
|
1353
|
+
PrintMutationInstructionRelative(
|
|
1354
|
+
"[IndexAdjustment] adjustImmediateMutationIndicesForDelayedMutations CANDIDATE for:",
|
|
1355
|
+
mutation,
|
|
1356
|
+
delayedMutation);
|
|
1357
|
+
candidateMutations.push_back(&delayedMutation);
|
|
1611
1358
|
}
|
|
1359
|
+
}
|
|
1612
1360
|
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
finalMutationsForConflictingAnimations.insert(
|
|
1616
|
-
finalMutationsForConflictingAnimations.end(),
|
|
1617
|
-
mutations.begin(),
|
|
1618
|
-
mutations.end());
|
|
1619
|
-
mutations = finalMutationsForConflictingAnimations;
|
|
1361
|
+
if (lastAnimationOnly) {
|
|
1362
|
+
break;
|
|
1620
1363
|
}
|
|
1621
|
-
}
|
|
1364
|
+
}
|
|
1622
1365
|
|
|
1623
|
-
//
|
|
1624
|
-
// we
|
|
1625
|
-
//
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1366
|
+
// While the mutation keeps being affected, keep checking. We use the vector
|
|
1367
|
+
// so we only perform one adjustment per delayed mutation. See comments at
|
|
1368
|
+
// bottom of adjustDelayedMutationIndicesForMutation for further explanation.
|
|
1369
|
+
bool changed = true;
|
|
1370
|
+
int adjustedDelta = 0;
|
|
1371
|
+
while (changed) {
|
|
1372
|
+
changed = false;
|
|
1373
|
+
candidateMutations.erase(
|
|
1374
|
+
std::remove_if(
|
|
1375
|
+
candidateMutations.begin(),
|
|
1376
|
+
candidateMutations.end(),
|
|
1377
|
+
[&changed, &mutation, &adjustedDelta, &isRemoveMutation](
|
|
1378
|
+
ShadowViewMutation *candidateMutation) {
|
|
1379
|
+
bool indexConflicts =
|
|
1380
|
+
(candidateMutation->index < mutation.index ||
|
|
1381
|
+
(isRemoveMutation &&
|
|
1382
|
+
candidateMutation->index == mutation.index));
|
|
1383
|
+
if (indexConflicts) {
|
|
1384
|
+
mutation.index++;
|
|
1385
|
+
adjustedDelta++;
|
|
1386
|
+
changed = true;
|
|
1387
|
+
PrintMutationInstructionRelative(
|
|
1388
|
+
"[IndexAdjustment] adjustImmediateMutationIndicesForDelayedMutations: Adjusting mutation UPWARD",
|
|
1389
|
+
mutation,
|
|
1390
|
+
*candidateMutation);
|
|
1391
|
+
return true;
|
|
1392
|
+
}
|
|
1393
|
+
return false;
|
|
1394
|
+
}),
|
|
1395
|
+
candidateMutations.end());
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1631
1398
|
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1399
|
+
void LayoutAnimationKeyFrameManager::adjustDelayedMutationIndicesForMutation(
|
|
1400
|
+
SurfaceId surfaceId,
|
|
1401
|
+
ShadowViewMutation const &mutation,
|
|
1402
|
+
bool skipLastAnimation) const {
|
|
1403
|
+
bool isRemoveMutation = mutation.type == ShadowViewMutation::Type::Remove;
|
|
1404
|
+
bool isInsertMutation = mutation.type == ShadowViewMutation::Type::Insert;
|
|
1405
|
+
auto tag = isRemoveMutation ? mutation.oldChildShadowView.tag
|
|
1406
|
+
: mutation.newChildShadowView.tag;
|
|
1407
|
+
react_native_assert(isRemoveMutation || isInsertMutation);
|
|
1408
|
+
|
|
1409
|
+
if (mutation.mutatedViewIsVirtual()) {
|
|
1410
|
+
PrintMutationInstruction(
|
|
1411
|
+
"[IndexAdjustment] Not calling adjustDelayedMutationIndicesForMutation, is virtual, for:",
|
|
1412
|
+
mutation);
|
|
1413
|
+
return;
|
|
1641
1414
|
}
|
|
1642
1415
|
|
|
1643
|
-
mutations
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
mutationsForAnimation.end());
|
|
1416
|
+
// First, collect all final mutations that could impact this immediate
|
|
1417
|
+
// mutation.
|
|
1418
|
+
std::vector<ShadowViewMutation *> candidateMutations{};
|
|
1647
1419
|
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1420
|
+
for (auto inflightAnimationIt =
|
|
1421
|
+
inflightAnimations_.rbegin() + (skipLastAnimation ? 1 : 0);
|
|
1422
|
+
inflightAnimationIt != inflightAnimations_.rend();
|
|
1423
|
+
inflightAnimationIt++) {
|
|
1424
|
+
auto &inflightAnimation = *inflightAnimationIt;
|
|
1425
|
+
|
|
1426
|
+
if (inflightAnimation.surfaceId != surfaceId) {
|
|
1427
|
+
continue;
|
|
1428
|
+
}
|
|
1656
1429
|
if (inflightAnimation.completed) {
|
|
1657
1430
|
continue;
|
|
1658
1431
|
}
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1432
|
+
|
|
1433
|
+
for (auto it = inflightAnimation.keyFrames.begin();
|
|
1434
|
+
it != inflightAnimation.keyFrames.end();
|
|
1435
|
+
it++) {
|
|
1436
|
+
auto &animatedKeyFrame = *it;
|
|
1437
|
+
|
|
1438
|
+
if (animatedKeyFrame.invalidated) {
|
|
1439
|
+
continue;
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
// Detect if they're in the same view hierarchy, but not equivalent
|
|
1443
|
+
// (We've already detected direct conflicts and handled them above)
|
|
1444
|
+
if (animatedKeyFrame.parentView.tag != mutation.parentShadowView.tag) {
|
|
1445
|
+
continue;
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
for (auto &finalAnimationMutation :
|
|
1449
|
+
animatedKeyFrame.finalMutationsForKeyFrame) {
|
|
1450
|
+
if (finalAnimationMutation.oldChildShadowView.tag == tag) {
|
|
1451
|
+
continue;
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
if (finalAnimationMutation.type != ShadowViewMutation::Type::Remove) {
|
|
1455
|
+
continue;
|
|
1456
|
+
}
|
|
1457
|
+
if (finalAnimationMutation.mutatedViewIsVirtual()) {
|
|
1458
|
+
continue;
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
PrintMutationInstructionRelative(
|
|
1462
|
+
"[IndexAdjustment] adjustDelayedMutationIndicesForMutation: CANDIDATE:",
|
|
1463
|
+
mutation,
|
|
1464
|
+
finalAnimationMutation);
|
|
1465
|
+
candidateMutations.push_back(&finalAnimationMutation);
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
// Because the finalAnimations are not sorted in any way, it is possible to
|
|
1471
|
+
// have some sequence like:
|
|
1472
|
+
// * DELAYED REMOVE 10 from {TAG}
|
|
1473
|
+
// * DELAYED REMOVE 9 from {TAG}
|
|
1474
|
+
// * ...
|
|
1475
|
+
// * DELAYED REMOVE 5 from {TAG}
|
|
1476
|
+
// with mutation: INSERT 6/REMOVE 6. This would cause the first few mutations
|
|
1477
|
+
// to *not* be adjusted, even though they would be impacted by mutation or
|
|
1478
|
+
// vice-versa after later adjustments are applied. Therefore, we just keep
|
|
1479
|
+
// recursing while there are any changes. This isn't great, but is good enough
|
|
1480
|
+
// for now until we change these data-structures.
|
|
1481
|
+
bool changed = true;
|
|
1482
|
+
while (changed) {
|
|
1483
|
+
changed = false;
|
|
1484
|
+
candidateMutations.erase(
|
|
1485
|
+
std::remove_if(
|
|
1486
|
+
candidateMutations.begin(),
|
|
1487
|
+
candidateMutations.end(),
|
|
1488
|
+
[&mutation, &isRemoveMutation, &isInsertMutation, &changed](
|
|
1489
|
+
ShadowViewMutation *candidateMutation) {
|
|
1490
|
+
if (isRemoveMutation &&
|
|
1491
|
+
mutation.index <= candidateMutation->index) {
|
|
1492
|
+
candidateMutation->index--;
|
|
1493
|
+
changed = true;
|
|
1494
|
+
PrintMutationInstructionRelative(
|
|
1495
|
+
"[IndexAdjustment] adjustDelayedMutationIndicesForMutation: Adjusting mutation DOWNWARD",
|
|
1496
|
+
mutation,
|
|
1497
|
+
*candidateMutation);
|
|
1498
|
+
return true;
|
|
1499
|
+
} else if (
|
|
1500
|
+
isInsertMutation &&
|
|
1501
|
+
mutation.index <= candidateMutation->index) {
|
|
1502
|
+
candidateMutation->index++;
|
|
1503
|
+
changed = true;
|
|
1504
|
+
PrintMutationInstructionRelative(
|
|
1505
|
+
"[IndexAdjustment] adjustDelayedMutationIndicesForMutation: Adjusting mutation UPWARD",
|
|
1506
|
+
mutation,
|
|
1507
|
+
*candidateMutation);
|
|
1508
|
+
return true;
|
|
1509
|
+
}
|
|
1510
|
+
return false;
|
|
1511
|
+
}),
|
|
1512
|
+
candidateMutations.end());
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
void LayoutAnimationKeyFrameManager::getAndEraseConflictingAnimations(
|
|
1517
|
+
SurfaceId surfaceId,
|
|
1518
|
+
ShadowViewMutationList const &mutations,
|
|
1519
|
+
std::vector<AnimationKeyFrame> &conflictingAnimations) const {
|
|
1520
|
+
ShadowViewMutationList localConflictingMutations{};
|
|
1521
|
+
for (auto const &mutation : mutations) {
|
|
1522
|
+
bool mutationIsCreateOrDelete =
|
|
1523
|
+
mutation.type == ShadowViewMutation::Type::Create ||
|
|
1524
|
+
mutation.type == ShadowViewMutation::Type::Delete;
|
|
1525
|
+
auto const &baselineShadowView =
|
|
1526
|
+
(mutation.type == ShadowViewMutation::Type::Insert ||
|
|
1527
|
+
mutation.type == ShadowViewMutation::Type::Create)
|
|
1528
|
+
? mutation.newChildShadowView
|
|
1529
|
+
: mutation.oldChildShadowView;
|
|
1530
|
+
auto baselineTag = baselineShadowView.tag;
|
|
1531
|
+
|
|
1532
|
+
for (auto &inflightAnimation : inflightAnimations_) {
|
|
1533
|
+
if (inflightAnimation.surfaceId != surfaceId) {
|
|
1662
1534
|
continue;
|
|
1663
1535
|
}
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
std::string msg = "Animation " + std::to_string(i) + " keyframe " +
|
|
1667
|
-
std::to_string(j) + ": Final Animation";
|
|
1668
|
-
PrintMutationInstruction(msg, finalMutation);
|
|
1669
|
-
}
|
|
1536
|
+
if (inflightAnimation.completed) {
|
|
1537
|
+
continue;
|
|
1670
1538
|
}
|
|
1671
|
-
}
|
|
1672
|
-
}
|
|
1673
|
-
LOG(ERROR) << "FINISHING DONE DISPLAYING ONGOING inflightAnimations_!";
|
|
1674
|
-
#endif
|
|
1675
|
-
|
|
1676
|
-
// Signal to delegate if all animations are complete, or if we were not
|
|
1677
|
-
// animating anything and now some animation exists.
|
|
1678
|
-
if (inflightAnimationsExistInitially && inflightAnimations_.empty()) {
|
|
1679
|
-
std::lock_guard<std::mutex> lock(layoutAnimationStatusDelegateMutex_);
|
|
1680
|
-
if (layoutAnimationStatusDelegate_ != nullptr) {
|
|
1681
|
-
layoutAnimationStatusDelegate_->onAllAnimationsComplete();
|
|
1682
|
-
}
|
|
1683
|
-
} else if (
|
|
1684
|
-
!inflightAnimationsExistInitially && !inflightAnimations_.empty()) {
|
|
1685
|
-
std::lock_guard<std::mutex> lock(layoutAnimationStatusDelegateMutex_);
|
|
1686
|
-
if (layoutAnimationStatusDelegate_ != nullptr) {
|
|
1687
|
-
layoutAnimationStatusDelegate_->onAnimationStarted();
|
|
1688
|
-
}
|
|
1689
|
-
}
|
|
1690
|
-
|
|
1691
|
-
return MountingTransaction{
|
|
1692
|
-
surfaceId, transactionNumber, std::move(mutations), telemetry};
|
|
1693
|
-
}
|
|
1694
1539
|
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
shadowView.componentHandle);
|
|
1699
|
-
}
|
|
1540
|
+
for (auto it = inflightAnimation.keyFrames.begin();
|
|
1541
|
+
it != inflightAnimation.keyFrames.end();) {
|
|
1542
|
+
auto &animatedKeyFrame = *it;
|
|
1700
1543
|
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
return componentDescriptorRegistry_->at(shadowView.componentHandle);
|
|
1705
|
-
}
|
|
1544
|
+
if (animatedKeyFrame.invalidated) {
|
|
1545
|
+
continue;
|
|
1546
|
+
}
|
|
1706
1547
|
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1548
|
+
// A conflict is when either: the animated node itself is mutated
|
|
1549
|
+
// directly; or, the parent of the node is created or deleted. In cases
|
|
1550
|
+
// of reparenting - say, the parent is deleted but the node was moved to
|
|
1551
|
+
// a different parent first - the reparenting (remove/insert) conflict
|
|
1552
|
+
// will be detected before we process the parent DELETE.
|
|
1553
|
+
// Parent deletion is important because deleting a parent recursively
|
|
1554
|
+
// deletes all children. If we previously deferred deletion of a child,
|
|
1555
|
+
// we need to force deletion/removal to happen immediately.
|
|
1556
|
+
bool conflicting = animatedKeyFrame.tag == baselineTag ||
|
|
1557
|
+
(mutationIsCreateOrDelete &&
|
|
1558
|
+
animatedKeyFrame.parentView.tag == baselineTag &&
|
|
1559
|
+
animatedKeyFrame.parentView.tag != 0);
|
|
1711
1560
|
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
* @param layoutAnimation
|
|
1718
|
-
* @param animatedMutation
|
|
1719
|
-
* @return
|
|
1720
|
-
*/
|
|
1721
|
-
ShadowView LayoutAnimationKeyFrameManager::createInterpolatedShadowView(
|
|
1722
|
-
double progress,
|
|
1723
|
-
ShadowView startingView,
|
|
1724
|
-
ShadowView finalView) const {
|
|
1725
|
-
react_native_assert(startingView.tag > 0);
|
|
1726
|
-
react_native_assert(finalView.tag > 0);
|
|
1727
|
-
if (!hasComponentDescriptorForShadowView(startingView)) {
|
|
1728
|
-
LOG(ERROR) << "No ComponentDescriptor for ShadowView being animated: ["
|
|
1729
|
-
<< startingView.tag << "]";
|
|
1730
|
-
react_native_assert(false);
|
|
1731
|
-
return finalView;
|
|
1732
|
-
}
|
|
1561
|
+
// Conflicting animation detected: if we're mutating a tag under
|
|
1562
|
+
// animation, or deleting the parent of a tag under animation, or
|
|
1563
|
+
// reparenting.
|
|
1564
|
+
if (conflicting) {
|
|
1565
|
+
animatedKeyFrame.invalidated = true;
|
|
1733
1566
|
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1567
|
+
// We construct a list of all conflicting animations, whether or not
|
|
1568
|
+
// they have a "final mutation" to execute. This is important with,
|
|
1569
|
+
// for example, "insert" mutations where the final update needs to set
|
|
1570
|
+
// opacity to "1", even if there's no final ShadowNode update.
|
|
1571
|
+
// TODO: don't animate virtual views in the first place?
|
|
1572
|
+
bool isVirtual = false;
|
|
1573
|
+
for (const auto &finalMutationForKeyFrame :
|
|
1574
|
+
animatedKeyFrame.finalMutationsForKeyFrame) {
|
|
1575
|
+
isVirtual =
|
|
1576
|
+
isVirtual || finalMutationForKeyFrame.mutatedViewIsVirtual();
|
|
1742
1577
|
|
|
1743
|
-
|
|
1744
|
-
|
|
1578
|
+
#ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
|
|
1579
|
+
PrintMutationInstructionRelative(
|
|
1580
|
+
"Found mutation that conflicts with existing in-flight animation:",
|
|
1581
|
+
mutation,
|
|
1582
|
+
finalMutationForKeyFrame);
|
|
1583
|
+
#endif
|
|
1584
|
+
}
|
|
1745
1585
|
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1586
|
+
conflictingAnimations.push_back(animatedKeyFrame);
|
|
1587
|
+
for (const auto &finalMutationForKeyFrame :
|
|
1588
|
+
animatedKeyFrame.finalMutationsForKeyFrame) {
|
|
1589
|
+
if (!isVirtual ||
|
|
1590
|
+
finalMutationForKeyFrame.type ==
|
|
1591
|
+
ShadowViewMutation::Type::Delete) {
|
|
1592
|
+
localConflictingMutations.push_back(finalMutationForKeyFrame);
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1755
1595
|
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1596
|
+
// Delete from existing animation
|
|
1597
|
+
it = inflightAnimation.keyFrames.erase(it);
|
|
1598
|
+
} else {
|
|
1599
|
+
it++;
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1760
1603
|
}
|
|
1761
1604
|
|
|
1762
|
-
//
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
return finalView;
|
|
1605
|
+
// Recurse, in case conflicting mutations conflict with other existing
|
|
1606
|
+
// animations
|
|
1607
|
+
if (!localConflictingMutations.empty()) {
|
|
1608
|
+
getAndEraseConflictingAnimations(
|
|
1609
|
+
surfaceId, localConflictingMutations, conflictingAnimations);
|
|
1768
1610
|
}
|
|
1769
|
-
|
|
1770
|
-
// Interpolate LayoutMetrics
|
|
1771
|
-
LayoutMetrics const &finalLayoutMetrics = finalView.layoutMetrics;
|
|
1772
|
-
LayoutMetrics const &baselineLayoutMetrics = startingView.layoutMetrics;
|
|
1773
|
-
LayoutMetrics interpolatedLayoutMetrics = finalLayoutMetrics;
|
|
1774
|
-
interpolatedLayoutMetrics.frame.origin.x = interpolateFloats(
|
|
1775
|
-
progress,
|
|
1776
|
-
baselineLayoutMetrics.frame.origin.x,
|
|
1777
|
-
finalLayoutMetrics.frame.origin.x);
|
|
1778
|
-
interpolatedLayoutMetrics.frame.origin.y = interpolateFloats(
|
|
1779
|
-
progress,
|
|
1780
|
-
baselineLayoutMetrics.frame.origin.y,
|
|
1781
|
-
finalLayoutMetrics.frame.origin.y);
|
|
1782
|
-
interpolatedLayoutMetrics.frame.size.width = interpolateFloats(
|
|
1783
|
-
progress,
|
|
1784
|
-
baselineLayoutMetrics.frame.size.width,
|
|
1785
|
-
finalLayoutMetrics.frame.size.width);
|
|
1786
|
-
interpolatedLayoutMetrics.frame.size.height = interpolateFloats(
|
|
1787
|
-
progress,
|
|
1788
|
-
baselineLayoutMetrics.frame.size.height,
|
|
1789
|
-
finalLayoutMetrics.frame.size.height);
|
|
1790
|
-
mutatedShadowView.layoutMetrics = interpolatedLayoutMetrics;
|
|
1791
|
-
|
|
1792
|
-
return mutatedShadowView;
|
|
1793
1611
|
}
|
|
1794
1612
|
|
|
1795
|
-
void LayoutAnimationKeyFrameManager::
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
if (
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
logPrefix + ": Queuing up Final Mutation:", finalMutation);
|
|
1807
|
-
// Copy so that if something else mutates the inflight animations,
|
|
1808
|
-
// it won't change this mutation after this point.
|
|
1809
|
-
auto mutation = ShadowViewMutation{
|
|
1810
|
-
finalMutation.type,
|
|
1811
|
-
finalMutation.parentShadowView,
|
|
1812
|
-
prev,
|
|
1813
|
-
finalMutation.newChildShadowView,
|
|
1814
|
-
finalMutation.index};
|
|
1815
|
-
react_native_assert(mutation.oldChildShadowView.tag > 0);
|
|
1816
|
-
react_native_assert(
|
|
1817
|
-
mutation.newChildShadowView.tag > 0 ||
|
|
1818
|
-
finalMutation.type == ShadowViewMutation::Remove ||
|
|
1819
|
-
finalMutation.type == ShadowViewMutation::Delete);
|
|
1820
|
-
mutationsList.push_back(mutation);
|
|
1821
|
-
if (finalMutation.newChildShadowView.tag > 0) {
|
|
1822
|
-
prev = finalMutation.newChildShadowView;
|
|
1823
|
-
}
|
|
1613
|
+
void LayoutAnimationKeyFrameManager::deleteAnimationsForStoppedSurfaces()
|
|
1614
|
+
const {
|
|
1615
|
+
bool inflightAnimationsExistInitially = !inflightAnimations_.empty();
|
|
1616
|
+
|
|
1617
|
+
// Execute stopSurface on any ongoing animations
|
|
1618
|
+
if (inflightAnimationsExistInitially) {
|
|
1619
|
+
better::set<SurfaceId> surfaceIdsToStop{};
|
|
1620
|
+
{
|
|
1621
|
+
std::lock_guard<std::mutex> lock(surfaceIdsToStopMutex_);
|
|
1622
|
+
surfaceIdsToStop = surfaceIdsToStop_;
|
|
1623
|
+
surfaceIdsToStop_.clear();
|
|
1824
1624
|
}
|
|
1825
|
-
} else {
|
|
1826
|
-
// If there's no final mutation associated, create a mutation that
|
|
1827
|
-
// corresponds to the animation being 100% complete. This is
|
|
1828
|
-
// important for, for example, INSERT mutations being animated from
|
|
1829
|
-
// opacity 0 to 1. If the animation is interrupted we must force the
|
|
1830
|
-
// View to be at opacity 1. For Android - since it passes along only
|
|
1831
|
-
// deltas, not an entire bag of props - generate an "animation"
|
|
1832
|
-
// frame corresponding to a final update for this view. Only then,
|
|
1833
|
-
// generate an update that will cause the ShadowTree to be
|
|
1834
|
-
// consistent with the Mounting layer by passing viewEnd,
|
|
1835
|
-
// unmodified, to the mounting layer. This helps with, for example,
|
|
1836
|
-
// opacity animations.
|
|
1837
|
-
// This is necessary for INSERT (create) and UPDATE (update) mutations, but
|
|
1838
|
-
// not REMOVE/DELETE mutations ("delete" animations).
|
|
1839
|
-
if (interrupted) {
|
|
1840
|
-
auto mutatedShadowView =
|
|
1841
|
-
createInterpolatedShadowView(1, keyframe.viewStart, keyframe.viewEnd);
|
|
1842
|
-
auto generatedPenultimateMutation = ShadowViewMutation::UpdateMutation(
|
|
1843
|
-
keyframe.viewPrev, mutatedShadowView);
|
|
1844
|
-
react_native_assert(
|
|
1845
|
-
generatedPenultimateMutation.oldChildShadowView.tag > 0);
|
|
1846
|
-
react_native_assert(
|
|
1847
|
-
generatedPenultimateMutation.newChildShadowView.tag > 0);
|
|
1848
|
-
PrintMutationInstruction(
|
|
1849
|
-
"Queueing up penultimate mutation instruction - synthetic",
|
|
1850
|
-
generatedPenultimateMutation);
|
|
1851
|
-
mutationsList.push_back(generatedPenultimateMutation);
|
|
1852
1625
|
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
PrintMutationInstruction(
|
|
1869
|
-
logPrefix +
|
|
1870
|
-
"Animation Complete: Queuing up Final Synthetic Mutation:",
|
|
1871
|
-
mutation);
|
|
1872
|
-
react_native_assert(mutation.oldChildShadowView.tag > 0);
|
|
1873
|
-
react_native_assert(mutation.newChildShadowView.tag > 0);
|
|
1874
|
-
mutationsList.push_back(mutation);
|
|
1626
|
+
for (auto it = inflightAnimations_.begin();
|
|
1627
|
+
it != inflightAnimations_.end();) {
|
|
1628
|
+
const auto &animation = *it;
|
|
1629
|
+
|
|
1630
|
+
#ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
|
|
1631
|
+
LOG(ERROR)
|
|
1632
|
+
<< "LayoutAnimations: stopping animation due to stopSurface on "
|
|
1633
|
+
<< surfaceId;
|
|
1634
|
+
#endif
|
|
1635
|
+
if (surfaceIdsToStop.find(animation.surfaceId) !=
|
|
1636
|
+
surfaceIdsToStop.end()) {
|
|
1637
|
+
it = inflightAnimations_.erase(it);
|
|
1638
|
+
} else {
|
|
1639
|
+
it++;
|
|
1640
|
+
}
|
|
1875
1641
|
}
|
|
1876
1642
|
}
|
|
1877
1643
|
}
|
|
1878
1644
|
|
|
1879
|
-
void LayoutAnimationKeyFrameManager::
|
|
1880
|
-
const
|
|
1881
|
-
if (
|
|
1645
|
+
void LayoutAnimationKeyFrameManager::simulateImagePropsMemoryAccess(
|
|
1646
|
+
ShadowViewMutationList const &mutations) const {
|
|
1647
|
+
if (!simulateImagePropsMemoryAccess_) {
|
|
1882
1648
|
return;
|
|
1883
1649
|
}
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
callbackWrappersPending_.push_back(std::move(copiedCallback));
|
|
1650
|
+
for (auto const &mutation : mutations) {
|
|
1651
|
+
if (mutation.type != ShadowViewMutation::Type::Insert) {
|
|
1652
|
+
continue;
|
|
1653
|
+
}
|
|
1654
|
+
if (strcmp(mutation.newChildShadowView.componentName, "Image") == 0) {
|
|
1655
|
+
auto const &imageProps = *std::static_pointer_cast<ImageProps const>(
|
|
1656
|
+
mutation.newChildShadowView.props);
|
|
1657
|
+
int temp = 0;
|
|
1658
|
+
switch (imageProps.resizeMode) {
|
|
1659
|
+
case ImageResizeMode::Cover:
|
|
1660
|
+
temp = 1;
|
|
1661
|
+
break;
|
|
1662
|
+
case ImageResizeMode::Contain:
|
|
1663
|
+
temp = 2;
|
|
1664
|
+
break;
|
|
1665
|
+
case ImageResizeMode::Stretch:
|
|
1666
|
+
temp = 3;
|
|
1667
|
+
break;
|
|
1668
|
+
case ImageResizeMode::Center:
|
|
1669
|
+
temp = 4;
|
|
1670
|
+
break;
|
|
1671
|
+
case ImageResizeMode::Repeat:
|
|
1672
|
+
temp = 5;
|
|
1673
|
+
break;
|
|
1674
|
+
}
|
|
1675
|
+
(void)temp;
|
|
1676
|
+
}
|
|
1912
1677
|
}
|
|
1913
1678
|
}
|
|
1914
1679
|
|