@office-iss/react-native-win32 0.76.2 → 0.77.0-preview.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/.eslintignore +1 -1
- package/.flowconfig +5 -1
- package/CHANGELOG.json +179 -53
- package/CHANGELOG.md +82 -28
- package/Libraries/ActionSheetIOS/ActionSheetIOS.d.ts +1 -0
- package/Libraries/ActionSheetIOS/ActionSheetIOS.js +13 -0
- package/Libraries/Animated/AnimatedEvent.js +1 -1
- package/Libraries/Animated/AnimatedImplementation.js +2 -2
- package/Libraries/Animated/NativeAnimatedAllowlist.js +20 -9
- package/Libraries/Animated/animations/Animation.js +60 -25
- package/Libraries/Animated/animations/DecayAnimation.js +26 -38
- package/Libraries/Animated/animations/SpringAnimation.js +33 -39
- package/Libraries/Animated/animations/TimingAnimation.js +34 -42
- package/Libraries/Animated/components/AnimatedFlatList.js +1 -1
- package/Libraries/Animated/components/AnimatedSectionList.js +3 -1
- package/Libraries/Animated/createAnimatedComponent.js +60 -33
- package/Libraries/Animated/nodes/AnimatedColor.js +1 -1
- package/Libraries/Animated/nodes/AnimatedInterpolation.js +1 -1
- package/Libraries/Animated/nodes/AnimatedNode.js +39 -45
- package/Libraries/Animated/nodes/AnimatedObject.js +13 -3
- package/Libraries/Animated/nodes/AnimatedProps.js +104 -46
- package/Libraries/Animated/nodes/AnimatedStyle.js +116 -39
- package/Libraries/Animated/nodes/AnimatedTransform.js +56 -23
- package/Libraries/Animated/nodes/AnimatedValue.js +1 -1
- package/Libraries/Animated/nodes/AnimatedWithChildren.js +1 -3
- package/Libraries/Animated/useAnimatedProps.js +41 -35
- package/Libraries/Components/AccessibilityInfo/AccessibilityInfo.d.ts +19 -3
- package/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js +77 -5
- package/Libraries/Components/AccessibilityInfo/AccessibilityInfo.win32.js +82 -5
- package/Libraries/Components/ActivityIndicator/ActivityIndicator.js +4 -4
- package/Libraries/Components/Button.js +9 -4
- package/Libraries/Components/Button.win32.js +12 -4
- package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.js +3 -1
- package/Libraries/Components/Keyboard/KeyboardAvoidingView.js +7 -0
- package/Libraries/Components/Pressable/Pressable.js +4 -4
- package/Libraries/Components/Pressable/Pressable.win32.js +4 -4
- package/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js +13 -7
- package/Libraries/Components/RefreshControl/__mocks__/RefreshControlMock.js +3 -2
- package/Libraries/Components/SafeAreaView/SafeAreaView.js +4 -4
- package/Libraries/Components/SafeAreaView/SafeAreaView.win32.js +4 -4
- package/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js +0 -1
- package/Libraries/Components/ScrollView/ScrollView.js +49 -88
- package/Libraries/Components/ScrollView/ScrollViewCommands.js +1 -1
- package/Libraries/Components/ScrollView/ScrollViewContext.js +2 -0
- package/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +0 -2
- package/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +8 -9
- package/Libraries/Components/Switch/Switch.js +8 -6
- package/Libraries/Components/TextInput/InputAccessoryView.js +1 -1
- package/Libraries/Components/TextInput/RCTMultilineTextInputNativeComponent.js +4 -4
- package/Libraries/Components/TextInput/RCTSingelineTextInputNativeComponent.js +6 -4
- package/Libraries/Components/TextInput/RCTTextInputViewConfig.js +2 -1
- package/Libraries/Components/TextInput/TextInput.d.ts +27 -4
- package/Libraries/Components/TextInput/TextInput.flow.js +36 -19
- package/Libraries/Components/TextInput/TextInput.js +37 -13
- package/Libraries/Components/TextInput/TextInput.win32.js +40 -15
- package/Libraries/Components/TextInput/TextInputState.js +11 -13
- package/Libraries/Components/TextInput/TextInputState.win32.js +13 -16
- package/Libraries/Components/TextInput/Win32TextInputNativeComponent.js +3 -0
- package/Libraries/Components/Touchable/BoundingDimensions.js +11 -3
- package/Libraries/Components/Touchable/Position.js +7 -2
- package/Libraries/Components/Touchable/Touchable.js +4 -0
- package/Libraries/Components/Touchable/Touchable.win32.js +4 -0
- package/Libraries/Components/Touchable/TouchableBounce.js +6 -2
- package/Libraries/Components/Touchable/TouchableHighlight.js +5 -5
- package/Libraries/Components/Touchable/TouchableOpacity.js +6 -5
- package/Libraries/Components/Touchable/TouchableWithoutFeedback.js +1 -2
- package/Libraries/Components/View/ReactNativeStyleAttributes.js +6 -1
- package/Libraries/Components/View/View.js +4 -4
- package/Libraries/Components/View/View.win32.js +4 -4
- package/Libraries/Components/View/ViewNativeComponent.js +6 -98
- package/Libraries/Components/View/ViewPropTypes.d.ts +7 -0
- package/Libraries/Components/View/ViewPropTypes.js +0 -3
- package/Libraries/Components/View/ViewPropTypes.win32.js +0 -3
- package/Libraries/Components/View/ViewWin32.js +1 -0
- package/Libraries/Core/ExceptionsManager.js +50 -29
- package/Libraries/Core/ReactNativeVersion.js +3 -3
- package/Libraries/Core/__mocks__/NativeExceptionsManager.js +0 -1
- package/Libraries/Core/setUpBatchedBridge.js +1 -10
- package/Libraries/Core/setUpDeveloperTools.js +1 -5
- package/Libraries/Core/setUpErrorHandling.js +20 -18
- package/Libraries/Core/setUpReactDevTools.js +107 -8
- package/Libraries/Core/setUpSegmentFetcher.js +1 -0
- package/Libraries/Core/setUpTimers.js +21 -18
- package/Libraries/Debugging/DebuggingOverlay.js +4 -5
- package/Libraries/Image/AssetSourceResolver.js +12 -1
- package/Libraries/Image/Image.android.js +1 -5
- package/Libraries/Image/Image.d.ts +20 -29
- package/Libraries/Image/Image.ios.js +0 -2
- package/Libraries/Image/Image.win32.js +0 -2
- package/Libraries/Image/ImageBackground.js +2 -5
- package/Libraries/Image/ImageProps.js +7 -6
- package/Libraries/Image/ImageResizeMode.d.ts +8 -1
- package/Libraries/Image/ImageResizeMode.js +4 -1
- package/Libraries/Image/ImageSource.d.ts +0 -2
- package/Libraries/Image/ImageSource.js +0 -2
- package/Libraries/Image/ImageTypes.flow.js +11 -9
- package/Libraries/Image/ImageUtils.js +6 -3
- package/Libraries/Image/ImageViewNativeComponent.js +5 -3
- package/Libraries/Inspector/Inspector.js +1 -0
- package/Libraries/Inspector/Inspector.win32.js +2 -1
- package/Libraries/Inspector/NetworkOverlay.js +4 -0
- package/Libraries/Inspector/ReactDevToolsOverlay.js +8 -14
- package/Libraries/Inspector/getInspectorDataForViewAtPoint.js +3 -5
- package/Libraries/Interaction/InteractionManager.js +6 -1
- package/Libraries/Interaction/InteractionManagerStub.js +176 -0
- package/Libraries/Interaction/TouchHistoryMath.js +22 -19
- package/Libraries/JSInspector/NetworkAgent.js +1 -1
- package/Libraries/Lists/FlatList.d.ts +1 -2
- package/Libraries/Lists/FlatList.js +2 -2
- package/Libraries/Lists/SectionListModern.js +7 -7
- package/Libraries/Lists/__flowtests__/FlatList-flowtest.js +2 -2
- package/Libraries/Lists/__flowtests__/SectionList-flowtest.js +1 -1
- package/Libraries/LogBox/Data/LogBoxData.js +3 -3
- package/Libraries/LogBox/LogBox.js +18 -5
- package/Libraries/LogBox/LogBoxInspectorContainer.js +1 -1
- package/Libraries/LogBox/LogBoxNotificationContainer.js +2 -2
- package/Libraries/LogBox/UI/AnsiHighlight.js +26 -17
- package/Libraries/LogBox/UI/LogBoxInspectorCodeFrame.js +6 -1
- package/Libraries/LogBox/UI/LogBoxInspectorCodeFrame.win32.js +6 -1
- package/Libraries/LogBox/UI/LogBoxInspectorHeader.js +1 -1
- package/Libraries/LogBox/UI/LogBoxInspectorHeader.win32.js +1 -1
- package/Libraries/LogBox/UI/LogBoxInspectorStackFrames.js +1 -1
- package/Libraries/LogBox/UI/LogBoxMessage.js +2 -2
- package/Libraries/Modal/Modal.d.ts +12 -0
- package/Libraries/Modal/Modal.js +31 -4
- package/Libraries/NativeComponent/BaseViewConfig.android.js +72 -1
- package/Libraries/NativeComponent/BaseViewConfig.ios.js +2 -1
- package/Libraries/NativeComponent/BaseViewConfig.win32.js +3 -11
- package/Libraries/NativeComponent/NativeComponentRegistry.js +3 -3
- package/Libraries/NativeComponent/StaticViewConfigValidator.js +0 -1
- package/Libraries/Network/FormData.js +11 -3
- package/Libraries/Network/XHRInterceptor.js +63 -14
- package/Libraries/Network/XMLHttpRequest.js +26 -1
- package/Libraries/NewAppScreen/components/HermesBadge.js +1 -1
- package/Libraries/PermissionsAndroid/PermissionsAndroid.d.ts +49 -2
- package/Libraries/PermissionsAndroid/PermissionsAndroid.js +4 -4
- package/Libraries/Pressability/HoverState.js +2 -0
- package/Libraries/Pressability/HoverState.win32.js +2 -0
- package/Libraries/Pressability/Pressability.js +2 -3
- package/Libraries/Pressability/Pressability.win32.js +2 -3
- package/Libraries/Pressability/usePressability.js +4 -1
- package/Libraries/ReactNative/AppContainer.js +1 -1
- package/Libraries/ReactNative/AppRegistry.js +1 -11
- package/Libraries/ReactNative/DisplayMode.js +1 -1
- package/Libraries/ReactNative/ReactFabricPublicInstance/ReactFabricHostComponent.js +2 -3
- package/Libraries/ReactNative/RendererImplementation.js +18 -17
- package/Libraries/ReactNative/getCachedComponentWithDebugName.js +1 -3
- package/Libraries/ReactNative/renderApplication.js +9 -8
- package/Libraries/ReactNative/requireNativeComponent.js +5 -2
- package/Libraries/Renderer/shims/ReactFabric.js +3 -3
- package/Libraries/Renderer/shims/ReactFeatureFlags.js +2 -2
- package/Libraries/Renderer/shims/ReactNative.js +3 -3
- package/Libraries/Renderer/shims/ReactNativeTypes.js +22 -35
- package/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js +5 -6
- package/Libraries/Renderer/shims/createReactNativeComponentClass.js +2 -2
- package/Libraries/StyleSheet/StyleSheet.js +7 -1
- package/Libraries/StyleSheet/StyleSheet.win32.js +7 -1
- package/Libraries/StyleSheet/StyleSheetTypes.d.ts +13 -2
- package/Libraries/StyleSheet/StyleSheetTypes.js +24 -6
- package/Libraries/StyleSheet/processBackgroundImage.js +87 -110
- package/Libraries/StyleSheet/processTransform.js +3 -34
- package/Libraries/Text/Text.js +248 -249
- package/Libraries/Text/Text.win32.js +282 -295
- package/Libraries/Text/TextNativeComponent.js +0 -1
- package/Libraries/TurboModule/TurboModuleRegistry.js +5 -5
- package/Libraries/Types/CoreEventTypes.d.ts +3 -10
- package/Libraries/Types/CoreEventTypes.js +4 -6
- package/Libraries/Types/CoreEventTypes.win32.js +4 -6
- package/Libraries/Utilities/Appearance.js +3 -1
- package/Libraries/Utilities/BackHandler.android.js +6 -18
- package/Libraries/Utilities/BackHandler.d.ts +0 -4
- package/Libraries/Utilities/BackHandler.ios.js +0 -7
- package/Libraries/Utilities/BackHandler.win32.js +6 -18
- package/Libraries/Utilities/FocusManager.win32.js +1 -1
- package/Libraries/Utilities/HMRClient.js +3 -4
- package/Libraries/Utilities/Platform.flow.js +2 -2
- package/Libraries/Utilities/Platform.flow.win32.js +3 -2
- package/Libraries/Utilities/__mocks__/BackHandler.js +3 -8
- package/Libraries/Utilities/codegenNativeComponent.js +1 -1
- package/Libraries/Utilities/useMergeRefs.js +26 -7
- package/Libraries/WebSocket/WebSocketEvent.js +4 -1
- package/Libraries/WebSocket/WebSocketInterceptor.js +31 -13
- package/Libraries/__flowtests__/ReactNativeTypes-flowtest.js +6 -5
- package/Libraries/promiseRejectionTrackingOptions.js +1 -1
- package/index.js +10 -3
- package/index.win32.js +10 -3
- package/jest/setup.js +36 -1
- package/overrides.json +37 -37
- package/package.json +20 -20
- package/src/private/animated/NativeAnimatedHelper.js +18 -16
- package/src/private/animated/NativeAnimatedHelper.win32.js +18 -15
- package/src/private/animated/useAnimatedPropsMemo.js +356 -0
- package/src/private/components/HScrollViewNativeComponents.js +1 -27
- package/src/private/components/SafeAreaView_INTERNAL_DO_NOT_USE.js +11 -8
- package/src/private/components/VScrollViewNativeComponents.js +2 -25
- package/src/private/debugging/ReactDevToolsSettingsManager.android.js +20 -0
- package/src/private/debugging/ReactDevToolsSettingsManager.ios.js +30 -0
- package/src/private/debugging/ReactDevToolsSettingsManager.win32.js +20 -0
- package/src/private/{fusebox → debugging}/setUpFuseboxReactDevToolsDispatcher.js +6 -0
- package/src/private/devmenu/DevMenu.d.ts +20 -0
- package/src/private/devmenu/DevMenu.js +31 -0
- package/src/private/featureflags/ReactNativeFeatureFlags.js +95 -86
- package/src/private/featureflags/ReactNativeFeatureFlagsBase.js +8 -2
- package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +17 -19
- package/src/private/fusebox/specs/NativeReactDevToolsRuntimeSettingsModule.js +34 -0
- package/src/private/setup/setUpDOM.js +14 -6
- package/src/private/setup/setUpMutationObserver.js +5 -0
- package/src/private/specs/components/AndroidHorizontalScrollContentViewNativeComponent.js +1 -0
- package/src/private/specs/components/RCTModalHostViewNativeComponent.js +8 -0
- package/src/private/specs/modules/NativeAccessibilityInfo.js +9 -0
- package/src/private/specs/modules/NativeAccessibilityInfoWin32.js +9 -0
- package/src/private/specs/modules/NativeAccessibilityManager.js +4 -0
- package/src/private/specs/modules/NativeActionSheetManager.js +2 -0
- package/src/private/specs/modules/NativeAppearance.js +4 -10
- package/src/private/specs/modules/NativeExceptionsManager.js +0 -12
- package/src/private/specs/modules/{NativeDevToolsSettingsManager.js → NativeReactDevToolsSettingsManager.js} +3 -5
- package/src/private/webapis/dom/geometry/DOMRect.js +2 -2
- package/src/private/webapis/dom/geometry/DOMRectReadOnly.js +2 -2
- package/src/private/webapis/dom/nodes/ReactNativeElement.js +2 -3
- package/src/private/webapis/intersectionobserver/IntersectionObserver.js +102 -11
- package/src/private/webapis/intersectionobserver/IntersectionObserverEntry.js +26 -0
- package/src/private/webapis/intersectionobserver/IntersectionObserverManager.js +1 -0
- package/src/private/webapis/intersectionobserver/specs/NativeIntersectionObserver.js +1 -0
- package/src/private/webapis/intersectionobserver/specs/__mocks__/NativeIntersectionObserver.js +9 -0
- package/src/private/webapis/performance/EventTiming.js +13 -8
- package/src/private/webapis/performance/Performance.js +66 -73
- package/src/private/webapis/performance/PerformanceEntry.js +2 -5
- package/src/private/webapis/performance/PerformanceObserver.js +65 -164
- package/src/private/webapis/performance/RawPerformanceEntry.js +1 -1
- package/src/private/webapis/performance/UserTiming.js +11 -7
- package/src/private/webapis/performance/Utilities.js +18 -0
- package/src/private/webapis/performance/specs/NativePerformance.js +71 -2
- package/src/private/webapis/performance/specs/__mocks__/NativePerformanceMock.js +267 -0
- package/src-win/Libraries/Components/AccessibilityInfo/AccessibilityInfo.d.ts +19 -3
- package/src-win/Libraries/Components/View/ViewPropTypes.d.ts +7 -0
- package/types/index.d.ts +1 -1
- package/types/public/ReactNativeTypes.d.ts +4 -8
- package/Libraries/DevToolsSettings/DevToolsSettingsManager.android.js +0 -35
- package/Libraries/DevToolsSettings/DevToolsSettingsManager.d.ts +0 -20
- package/Libraries/DevToolsSettings/DevToolsSettingsManager.ios.js +0 -49
- package/Libraries/DevToolsSettings/DevToolsSettingsManager.win32.js +0 -35
- package/Libraries/DevToolsSettings/NativeDevToolsSettingsManager.js +0 -13
- package/Libraries/ReactNative/ReactFabricInternals.js +0 -17
- package/src/private/components/useSyncOnScroll.js +0 -48
- package/src/private/webapis/performance/specs/NativePerformanceObserver.js +0 -61
- package/src/private/webapis/performance/specs/__mocks__/NativePerformance.js +0 -67
- package/src/private/webapis/performance/specs/__mocks__/NativePerformanceObserver.js +0 -127
- package/types/experimental.d.ts +0 -59
- /package/src/private/{fusebox → debugging}/FuseboxSessionObserver.js +0 -0
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
* @format
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
import type {AnimatedPropsAllowlist} from './nodes/AnimatedProps';
|
|
12
|
+
|
|
11
13
|
import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNativeFeatureFlags';
|
|
12
14
|
|
|
13
15
|
/**
|
|
@@ -16,7 +18,7 @@ import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNa
|
|
|
16
18
|
* In general native animated implementation should support any numeric or color property that
|
|
17
19
|
* doesn't need to be updated through the shadow view hierarchy (all non-layout properties).
|
|
18
20
|
*/
|
|
19
|
-
const SUPPORTED_COLOR_STYLES: {[string]:
|
|
21
|
+
const SUPPORTED_COLOR_STYLES: {[string]: true} = {
|
|
20
22
|
backgroundColor: true,
|
|
21
23
|
borderBottomColor: true,
|
|
22
24
|
borderColor: true,
|
|
@@ -29,7 +31,7 @@ const SUPPORTED_COLOR_STYLES: {[string]: boolean} = {
|
|
|
29
31
|
tintColor: true,
|
|
30
32
|
};
|
|
31
33
|
|
|
32
|
-
const SUPPORTED_STYLES: {[string]:
|
|
34
|
+
const SUPPORTED_STYLES: {[string]: true} = {
|
|
33
35
|
...SUPPORTED_COLOR_STYLES,
|
|
34
36
|
borderBottomEndRadius: true,
|
|
35
37
|
borderBottomLeftRadius: true,
|
|
@@ -58,7 +60,7 @@ const SUPPORTED_STYLES: {[string]: boolean} = {
|
|
|
58
60
|
translateY: true,
|
|
59
61
|
};
|
|
60
62
|
|
|
61
|
-
const SUPPORTED_TRANSFORMS: {[string]:
|
|
63
|
+
const SUPPORTED_TRANSFORMS: {[string]: true} = {
|
|
62
64
|
translateX: true,
|
|
63
65
|
translateY: true,
|
|
64
66
|
scale: true,
|
|
@@ -71,10 +73,12 @@ const SUPPORTED_TRANSFORMS: {[string]: boolean} = {
|
|
|
71
73
|
perspective: true,
|
|
72
74
|
skewX: true,
|
|
73
75
|
skewY: true,
|
|
74
|
-
|
|
76
|
+
...(ReactNativeFeatureFlags.shouldUseAnimatedObjectForTransform()
|
|
77
|
+
? {matrix: true}
|
|
78
|
+
: {}),
|
|
75
79
|
};
|
|
76
80
|
|
|
77
|
-
const SUPPORTED_INTERPOLATION_PARAMS: {[string]:
|
|
81
|
+
const SUPPORTED_INTERPOLATION_PARAMS: {[string]: true} = {
|
|
78
82
|
inputRange: true,
|
|
79
83
|
outputRange: true,
|
|
80
84
|
extrapolate: true,
|
|
@@ -82,6 +86,13 @@ const SUPPORTED_INTERPOLATION_PARAMS: {[string]: boolean} = {
|
|
|
82
86
|
extrapolateLeft: true,
|
|
83
87
|
};
|
|
84
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Default allowlist for component props that support native animated values.
|
|
91
|
+
*/
|
|
92
|
+
export default {
|
|
93
|
+
style: SUPPORTED_STYLES,
|
|
94
|
+
} as AnimatedPropsAllowlist;
|
|
95
|
+
|
|
85
96
|
export function allowInterpolationParam(param: string): void {
|
|
86
97
|
SUPPORTED_INTERPOLATION_PARAMS[param] = true;
|
|
87
98
|
}
|
|
@@ -95,17 +106,17 @@ export function allowTransformProp(prop: string): void {
|
|
|
95
106
|
}
|
|
96
107
|
|
|
97
108
|
export function isSupportedColorStyleProp(prop: string): boolean {
|
|
98
|
-
return SUPPORTED_COLOR_STYLES
|
|
109
|
+
return SUPPORTED_COLOR_STYLES.hasOwnProperty(prop);
|
|
99
110
|
}
|
|
100
111
|
|
|
101
112
|
export function isSupportedInterpolationParam(param: string): boolean {
|
|
102
|
-
return SUPPORTED_INTERPOLATION_PARAMS
|
|
113
|
+
return SUPPORTED_INTERPOLATION_PARAMS.hasOwnProperty(param);
|
|
103
114
|
}
|
|
104
115
|
|
|
105
116
|
export function isSupportedStyleProp(prop: string): boolean {
|
|
106
|
-
return SUPPORTED_STYLES
|
|
117
|
+
return SUPPORTED_STYLES.hasOwnProperty(prop);
|
|
107
118
|
}
|
|
108
119
|
|
|
109
120
|
export function isSupportedTransformProp(prop: string): boolean {
|
|
110
|
-
return SUPPORTED_TRANSFORMS
|
|
121
|
+
return SUPPORTED_TRANSFORMS.hasOwnProperty(prop);
|
|
111
122
|
}
|
|
@@ -4,31 +4,30 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @flow
|
|
7
|
+
* @flow strict-local
|
|
8
8
|
* @format
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
'use strict';
|
|
12
|
-
|
|
13
11
|
import type {PlatformConfig} from '../AnimatedPlatformConfig';
|
|
14
12
|
import type AnimatedNode from '../nodes/AnimatedNode';
|
|
15
13
|
import type AnimatedValue from '../nodes/AnimatedValue';
|
|
16
14
|
|
|
17
|
-
import * as ReactNativeFeatureFlags from '../../../src/private/featureflags/ReactNativeFeatureFlags';
|
|
18
15
|
import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper';
|
|
16
|
+
import * as ReactNativeFeatureFlags from '../../../src/private/featureflags/ReactNativeFeatureFlags';
|
|
19
17
|
import AnimatedProps from '../nodes/AnimatedProps';
|
|
20
18
|
|
|
21
19
|
export type EndResult = {finished: boolean, value?: number, ...};
|
|
22
20
|
export type EndCallback = (result: EndResult) => void;
|
|
23
21
|
|
|
24
|
-
export type AnimationConfig = {
|
|
22
|
+
export type AnimationConfig = $ReadOnly<{
|
|
25
23
|
isInteraction?: boolean,
|
|
26
24
|
useNativeDriver: boolean,
|
|
27
25
|
platformConfig?: PlatformConfig,
|
|
28
26
|
onComplete?: ?EndCallback,
|
|
29
27
|
iterations?: number,
|
|
30
28
|
isLooping?: boolean,
|
|
31
|
-
|
|
29
|
+
...
|
|
30
|
+
}>;
|
|
32
31
|
|
|
33
32
|
let startNativeAnimationNextId = 1;
|
|
34
33
|
|
|
@@ -36,13 +35,23 @@ let startNativeAnimationNextId = 1;
|
|
|
36
35
|
// Once an animation has been stopped or finished its course, it will
|
|
37
36
|
// not be reused.
|
|
38
37
|
export default class Animation {
|
|
38
|
+
#nativeID: ?number;
|
|
39
|
+
#onEnd: ?EndCallback;
|
|
40
|
+
#useNativeDriver: boolean;
|
|
41
|
+
|
|
39
42
|
__active: boolean;
|
|
40
43
|
__isInteraction: boolean;
|
|
41
|
-
__onEnd: ?EndCallback;
|
|
42
|
-
__iterations: number;
|
|
43
44
|
__isLooping: ?boolean;
|
|
45
|
+
__iterations: number;
|
|
46
|
+
|
|
47
|
+
constructor(config: AnimationConfig) {
|
|
48
|
+
this.#useNativeDriver = NativeAnimatedHelper.shouldUseNativeDriver(config);
|
|
44
49
|
|
|
45
|
-
|
|
50
|
+
this.__active = false;
|
|
51
|
+
this.__isInteraction = config.isInteraction ?? !this.#useNativeDriver;
|
|
52
|
+
this.__isLooping = config.isLooping;
|
|
53
|
+
this.__iterations = config.iterations ?? 1;
|
|
54
|
+
}
|
|
46
55
|
|
|
47
56
|
start(
|
|
48
57
|
fromValue: number,
|
|
@@ -50,27 +59,35 @@ export default class Animation {
|
|
|
50
59
|
onEnd: ?EndCallback,
|
|
51
60
|
previousAnimation: ?Animation,
|
|
52
61
|
animatedValue: AnimatedValue,
|
|
53
|
-
): void {
|
|
62
|
+
): void {
|
|
63
|
+
if (!this.#useNativeDriver && animatedValue.__isNative === true) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
'Attempting to run JS driven animation on animated node ' +
|
|
66
|
+
'that has been moved to "native" earlier by starting an ' +
|
|
67
|
+
'animation with `useNativeDriver: true`',
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
this.#onEnd = onEnd;
|
|
72
|
+
this.__active = true;
|
|
73
|
+
}
|
|
54
74
|
|
|
55
75
|
stop(): void {
|
|
56
|
-
if (this
|
|
57
|
-
NativeAnimatedHelper.API.stopAnimation(this
|
|
76
|
+
if (this.#nativeID != null) {
|
|
77
|
+
NativeAnimatedHelper.API.stopAnimation(this.#nativeID);
|
|
58
78
|
}
|
|
79
|
+
this.__active = false;
|
|
59
80
|
}
|
|
60
81
|
|
|
61
|
-
__getNativeAnimationConfig():
|
|
82
|
+
__getNativeAnimationConfig(): $ReadOnly<{
|
|
83
|
+
platformConfig: ?PlatformConfig,
|
|
84
|
+
...
|
|
85
|
+
}> {
|
|
62
86
|
// Subclasses that have corresponding animation implementation done in native
|
|
63
87
|
// should override this method
|
|
64
88
|
throw new Error('This animation type cannot be offloaded to native');
|
|
65
89
|
}
|
|
66
90
|
|
|
67
|
-
// Helper function for subclasses to make sure onEnd is only called once.
|
|
68
|
-
__debouncedOnEnd(result: EndResult): void {
|
|
69
|
-
const onEnd = this.__onEnd;
|
|
70
|
-
this.__onEnd = null;
|
|
71
|
-
onEnd && onEnd(result);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
91
|
__findAnimatedPropsNodes(node: AnimatedNode): Array<AnimatedProps> {
|
|
75
92
|
const result = [];
|
|
76
93
|
|
|
@@ -86,7 +103,11 @@ export default class Animation {
|
|
|
86
103
|
return result;
|
|
87
104
|
}
|
|
88
105
|
|
|
89
|
-
|
|
106
|
+
__startAnimationIfNative(animatedValue: AnimatedValue): boolean {
|
|
107
|
+
if (!this.#useNativeDriver) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
|
|
90
111
|
const startNativeAnimationWaitId = `${startNativeAnimationNextId}:startAnimation`;
|
|
91
112
|
startNativeAnimationNextId += 1;
|
|
92
113
|
NativeAnimatedHelper.API.setWaitingForIdentifier(
|
|
@@ -95,13 +116,13 @@ export default class Animation {
|
|
|
95
116
|
try {
|
|
96
117
|
const config = this.__getNativeAnimationConfig();
|
|
97
118
|
animatedValue.__makeNative(config.platformConfig);
|
|
98
|
-
this
|
|
119
|
+
this.#nativeID = NativeAnimatedHelper.generateNewAnimationId();
|
|
99
120
|
NativeAnimatedHelper.API.startAnimatingNode(
|
|
100
|
-
this
|
|
121
|
+
this.#nativeID,
|
|
101
122
|
animatedValue.__getNativeTag(),
|
|
102
123
|
config,
|
|
103
124
|
result => {
|
|
104
|
-
this.
|
|
125
|
+
this.__notifyAnimationEnd(result);
|
|
105
126
|
|
|
106
127
|
// When using natively driven animations, once the animation completes,
|
|
107
128
|
// we need to ensure that the JS side nodes are synced with the updated
|
|
@@ -112,7 +133,7 @@ export default class Animation {
|
|
|
112
133
|
|
|
113
134
|
if (
|
|
114
135
|
ReactNativeFeatureFlags.shouldSkipStateUpdatesForLoopingAnimations() &&
|
|
115
|
-
this.__isLooping
|
|
136
|
+
this.__isLooping === true
|
|
116
137
|
) {
|
|
117
138
|
return;
|
|
118
139
|
}
|
|
@@ -125,6 +146,8 @@ export default class Animation {
|
|
|
125
146
|
}
|
|
126
147
|
},
|
|
127
148
|
);
|
|
149
|
+
|
|
150
|
+
return true;
|
|
128
151
|
} catch (e) {
|
|
129
152
|
throw e;
|
|
130
153
|
} finally {
|
|
@@ -133,4 +156,16 @@ export default class Animation {
|
|
|
133
156
|
);
|
|
134
157
|
}
|
|
135
158
|
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Notify the completion callback that the animation has ended. The completion
|
|
162
|
+
* callback will never be called more than once.
|
|
163
|
+
*/
|
|
164
|
+
__notifyAnimationEnd(result: EndResult): void {
|
|
165
|
+
const callback = this.#onEnd;
|
|
166
|
+
if (callback != null) {
|
|
167
|
+
this.#onEnd = null;
|
|
168
|
+
callback(result);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
136
171
|
}
|
|
@@ -4,36 +4,35 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @flow
|
|
7
|
+
* @flow strict-local
|
|
8
8
|
* @format
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
'use strict';
|
|
12
|
-
|
|
13
11
|
import type {PlatformConfig} from '../AnimatedPlatformConfig';
|
|
14
12
|
import type AnimatedValue from '../nodes/AnimatedValue';
|
|
15
13
|
import type {AnimationConfig, EndCallback} from './Animation';
|
|
16
14
|
|
|
17
|
-
import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper';
|
|
18
15
|
import Animation from './Animation';
|
|
19
16
|
|
|
20
|
-
export type DecayAnimationConfig = {
|
|
17
|
+
export type DecayAnimationConfig = $ReadOnly<{
|
|
21
18
|
...AnimationConfig,
|
|
22
19
|
velocity:
|
|
23
20
|
| number
|
|
24
|
-
| {
|
|
21
|
+
| $ReadOnly<{
|
|
25
22
|
x: number,
|
|
26
23
|
y: number,
|
|
27
24
|
...
|
|
28
|
-
}
|
|
25
|
+
}>,
|
|
29
26
|
deceleration?: number,
|
|
30
|
-
|
|
27
|
+
...
|
|
28
|
+
}>;
|
|
31
29
|
|
|
32
|
-
export type DecayAnimationConfigSingle = {
|
|
30
|
+
export type DecayAnimationConfigSingle = $ReadOnly<{
|
|
33
31
|
...AnimationConfig,
|
|
34
32
|
velocity: number,
|
|
35
33
|
deceleration?: number,
|
|
36
|
-
|
|
34
|
+
...
|
|
35
|
+
}>;
|
|
37
36
|
|
|
38
37
|
export default class DecayAnimation extends Animation {
|
|
39
38
|
_startTime: number;
|
|
@@ -42,27 +41,25 @@ export default class DecayAnimation extends Animation {
|
|
|
42
41
|
_deceleration: number;
|
|
43
42
|
_velocity: number;
|
|
44
43
|
_onUpdate: (value: number) => void;
|
|
45
|
-
_animationFrame:
|
|
46
|
-
_useNativeDriver: boolean;
|
|
44
|
+
_animationFrame: ?AnimationFrameID;
|
|
47
45
|
_platformConfig: ?PlatformConfig;
|
|
48
46
|
|
|
49
47
|
constructor(config: DecayAnimationConfigSingle) {
|
|
50
|
-
super();
|
|
48
|
+
super(config);
|
|
49
|
+
|
|
51
50
|
this._deceleration = config.deceleration ?? 0.998;
|
|
52
51
|
this._velocity = config.velocity;
|
|
53
|
-
this._useNativeDriver = NativeAnimatedHelper.shouldUseNativeDriver(config);
|
|
54
52
|
this._platformConfig = config.platformConfig;
|
|
55
|
-
this.__isInteraction = config.isInteraction ?? !this._useNativeDriver;
|
|
56
|
-
this.__iterations = config.iterations ?? 1;
|
|
57
53
|
}
|
|
58
54
|
|
|
59
|
-
__getNativeAnimationConfig(): {
|
|
55
|
+
__getNativeAnimationConfig(): $ReadOnly<{
|
|
60
56
|
deceleration: number,
|
|
61
57
|
iterations: number,
|
|
62
58
|
platformConfig: ?PlatformConfig,
|
|
63
|
-
type:
|
|
59
|
+
type: 'decay',
|
|
64
60
|
velocity: number,
|
|
65
|
-
|
|
61
|
+
...
|
|
62
|
+
}> {
|
|
66
63
|
return {
|
|
67
64
|
type: 'decay',
|
|
68
65
|
deceleration: this._deceleration,
|
|
@@ -79,26 +76,16 @@ export default class DecayAnimation extends Animation {
|
|
|
79
76
|
previousAnimation: ?Animation,
|
|
80
77
|
animatedValue: AnimatedValue,
|
|
81
78
|
): void {
|
|
82
|
-
|
|
79
|
+
super.start(fromValue, onUpdate, onEnd, previousAnimation, animatedValue);
|
|
80
|
+
|
|
83
81
|
this._lastValue = fromValue;
|
|
84
82
|
this._fromValue = fromValue;
|
|
85
83
|
this._onUpdate = onUpdate;
|
|
86
|
-
this.__onEnd = onEnd;
|
|
87
84
|
this._startTime = Date.now();
|
|
88
85
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
'that has been moved to "native" earlier by starting an ' +
|
|
93
|
-
'animation with `useNativeDriver: true`',
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (this._useNativeDriver) {
|
|
98
|
-
this.__startNativeAnimation(animatedValue);
|
|
99
|
-
} else {
|
|
100
|
-
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
|
|
101
|
-
this._animationFrame = requestAnimationFrame(this.onUpdate.bind(this));
|
|
86
|
+
const useNativeDriver = this.__startAnimationIfNative(animatedValue);
|
|
87
|
+
if (!useNativeDriver) {
|
|
88
|
+
this._animationFrame = requestAnimationFrame(() => this.onUpdate());
|
|
102
89
|
}
|
|
103
90
|
}
|
|
104
91
|
|
|
@@ -113,7 +100,7 @@ export default class DecayAnimation extends Animation {
|
|
|
113
100
|
this._onUpdate(value);
|
|
114
101
|
|
|
115
102
|
if (Math.abs(this._lastValue - value) < 0.1) {
|
|
116
|
-
this.
|
|
103
|
+
this.__notifyAnimationEnd({finished: true});
|
|
117
104
|
return;
|
|
118
105
|
}
|
|
119
106
|
|
|
@@ -126,8 +113,9 @@ export default class DecayAnimation extends Animation {
|
|
|
126
113
|
|
|
127
114
|
stop(): void {
|
|
128
115
|
super.stop();
|
|
129
|
-
this.
|
|
130
|
-
|
|
131
|
-
|
|
116
|
+
if (this._animationFrame != null) {
|
|
117
|
+
global.cancelAnimationFrame(this._animationFrame);
|
|
118
|
+
}
|
|
119
|
+
this.__notifyAnimationEnd({finished: false});
|
|
132
120
|
}
|
|
133
121
|
}
|
|
@@ -4,25 +4,22 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @flow
|
|
7
|
+
* @flow strict-local
|
|
8
8
|
* @format
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
'use strict';
|
|
12
|
-
|
|
13
11
|
import type {PlatformConfig} from '../AnimatedPlatformConfig';
|
|
14
12
|
import type AnimatedInterpolation from '../nodes/AnimatedInterpolation';
|
|
15
13
|
import type AnimatedValue from '../nodes/AnimatedValue';
|
|
16
14
|
import type AnimatedValueXY from '../nodes/AnimatedValueXY';
|
|
17
15
|
import type {AnimationConfig, EndCallback} from './Animation';
|
|
18
16
|
|
|
19
|
-
import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper';
|
|
20
17
|
import AnimatedColor from '../nodes/AnimatedColor';
|
|
21
18
|
import * as SpringConfig from '../SpringConfig';
|
|
22
19
|
import Animation from './Animation';
|
|
23
20
|
import invariant from 'invariant';
|
|
24
21
|
|
|
25
|
-
export type SpringAnimationConfig = {
|
|
22
|
+
export type SpringAnimationConfig = $ReadOnly<{
|
|
26
23
|
...AnimationConfig,
|
|
27
24
|
toValue:
|
|
28
25
|
| number
|
|
@@ -47,11 +44,11 @@ export type SpringAnimationConfig = {
|
|
|
47
44
|
restSpeedThreshold?: number,
|
|
48
45
|
velocity?:
|
|
49
46
|
| number
|
|
50
|
-
| {
|
|
47
|
+
| $ReadOnly<{
|
|
51
48
|
x: number,
|
|
52
49
|
y: number,
|
|
53
50
|
...
|
|
54
|
-
}
|
|
51
|
+
}>,
|
|
55
52
|
bounciness?: number,
|
|
56
53
|
speed?: number,
|
|
57
54
|
tension?: number,
|
|
@@ -60,9 +57,10 @@ export type SpringAnimationConfig = {
|
|
|
60
57
|
damping?: number,
|
|
61
58
|
mass?: number,
|
|
62
59
|
delay?: number,
|
|
63
|
-
|
|
60
|
+
...
|
|
61
|
+
}>;
|
|
64
62
|
|
|
65
|
-
export type SpringAnimationConfigSingle = {
|
|
63
|
+
export type SpringAnimationConfigSingle = $ReadOnly<{
|
|
66
64
|
...AnimationConfig,
|
|
67
65
|
toValue: number,
|
|
68
66
|
overshootClamping?: boolean,
|
|
@@ -77,7 +75,14 @@ export type SpringAnimationConfigSingle = {
|
|
|
77
75
|
damping?: number,
|
|
78
76
|
mass?: number,
|
|
79
77
|
delay?: number,
|
|
80
|
-
|
|
78
|
+
...
|
|
79
|
+
}>;
|
|
80
|
+
|
|
81
|
+
opaque type SpringAnimationInternalState = $ReadOnly<{
|
|
82
|
+
lastPosition: number,
|
|
83
|
+
lastVelocity: number,
|
|
84
|
+
lastTime: number,
|
|
85
|
+
}>;
|
|
81
86
|
|
|
82
87
|
export default class SpringAnimation extends Animation {
|
|
83
88
|
_overshootClamping: boolean;
|
|
@@ -93,17 +98,16 @@ export default class SpringAnimation extends Animation {
|
|
|
93
98
|
_mass: number;
|
|
94
99
|
_initialVelocity: number;
|
|
95
100
|
_delay: number;
|
|
96
|
-
_timeout:
|
|
101
|
+
_timeout: ?TimeoutID;
|
|
97
102
|
_startTime: number;
|
|
98
103
|
_lastTime: number;
|
|
99
104
|
_frameTime: number;
|
|
100
105
|
_onUpdate: (value: number) => void;
|
|
101
|
-
_animationFrame:
|
|
102
|
-
_useNativeDriver: boolean;
|
|
106
|
+
_animationFrame: ?AnimationFrameID;
|
|
103
107
|
_platformConfig: ?PlatformConfig;
|
|
104
108
|
|
|
105
109
|
constructor(config: SpringAnimationConfigSingle) {
|
|
106
|
-
super();
|
|
110
|
+
super(config);
|
|
107
111
|
|
|
108
112
|
this._overshootClamping = config.overshootClamping ?? false;
|
|
109
113
|
this._restDisplacementThreshold = config.restDisplacementThreshold ?? 0.001;
|
|
@@ -112,10 +116,7 @@ export default class SpringAnimation extends Animation {
|
|
|
112
116
|
this._lastVelocity = config.velocity ?? 0;
|
|
113
117
|
this._toValue = config.toValue;
|
|
114
118
|
this._delay = config.delay ?? 0;
|
|
115
|
-
this._useNativeDriver = NativeAnimatedHelper.shouldUseNativeDriver(config);
|
|
116
119
|
this._platformConfig = config.platformConfig;
|
|
117
|
-
this.__isInteraction = config.isInteraction ?? !this._useNativeDriver;
|
|
118
|
-
this.__iterations = config.iterations ?? 1;
|
|
119
120
|
|
|
120
121
|
if (
|
|
121
122
|
config.stiffness !== undefined ||
|
|
@@ -167,7 +168,7 @@ export default class SpringAnimation extends Animation {
|
|
|
167
168
|
invariant(this._mass > 0, 'Mass value must be greater than 0');
|
|
168
169
|
}
|
|
169
170
|
|
|
170
|
-
__getNativeAnimationConfig(): {
|
|
171
|
+
__getNativeAnimationConfig(): $ReadOnly<{
|
|
171
172
|
damping: number,
|
|
172
173
|
initialVelocity: number,
|
|
173
174
|
iterations: number,
|
|
@@ -177,9 +178,10 @@ export default class SpringAnimation extends Animation {
|
|
|
177
178
|
restDisplacementThreshold: number,
|
|
178
179
|
restSpeedThreshold: number,
|
|
179
180
|
stiffness: number,
|
|
180
|
-
toValue:
|
|
181
|
-
type:
|
|
182
|
-
|
|
181
|
+
toValue: number,
|
|
182
|
+
type: 'spring',
|
|
183
|
+
...
|
|
184
|
+
}> {
|
|
183
185
|
return {
|
|
184
186
|
type: 'spring',
|
|
185
187
|
overshootClamping: this._overshootClamping,
|
|
@@ -202,12 +204,12 @@ export default class SpringAnimation extends Animation {
|
|
|
202
204
|
previousAnimation: ?Animation,
|
|
203
205
|
animatedValue: AnimatedValue,
|
|
204
206
|
): void {
|
|
205
|
-
|
|
207
|
+
super.start(fromValue, onUpdate, onEnd, previousAnimation, animatedValue);
|
|
208
|
+
|
|
206
209
|
this._startPosition = fromValue;
|
|
207
210
|
this._lastPosition = this._startPosition;
|
|
208
211
|
|
|
209
212
|
this._onUpdate = onUpdate;
|
|
210
|
-
this.__onEnd = onEnd;
|
|
211
213
|
this._lastTime = Date.now();
|
|
212
214
|
this._frameTime = 0.0;
|
|
213
215
|
|
|
@@ -221,17 +223,8 @@ export default class SpringAnimation extends Animation {
|
|
|
221
223
|
}
|
|
222
224
|
|
|
223
225
|
const start = () => {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
'Attempting to run JS driven animation on animated node ' +
|
|
227
|
-
'that has been moved to "native" earlier by starting an ' +
|
|
228
|
-
'animation with `useNativeDriver: true`',
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
if (this._useNativeDriver) {
|
|
233
|
-
this.__startNativeAnimation(animatedValue);
|
|
234
|
-
} else {
|
|
226
|
+
const useNativeDriver = this.__startAnimationIfNative(animatedValue);
|
|
227
|
+
if (!useNativeDriver) {
|
|
235
228
|
this.onUpdate();
|
|
236
229
|
}
|
|
237
230
|
};
|
|
@@ -244,7 +237,7 @@ export default class SpringAnimation extends Animation {
|
|
|
244
237
|
}
|
|
245
238
|
}
|
|
246
239
|
|
|
247
|
-
getInternalState():
|
|
240
|
+
getInternalState(): SpringAnimationInternalState {
|
|
248
241
|
return {
|
|
249
242
|
lastPosition: this._lastPosition,
|
|
250
243
|
lastVelocity: this._lastVelocity,
|
|
@@ -361,7 +354,7 @@ export default class SpringAnimation extends Animation {
|
|
|
361
354
|
this._onUpdate(this._toValue);
|
|
362
355
|
}
|
|
363
356
|
|
|
364
|
-
this.
|
|
357
|
+
this.__notifyAnimationEnd({finished: true});
|
|
365
358
|
return;
|
|
366
359
|
}
|
|
367
360
|
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
|
|
@@ -370,9 +363,10 @@ export default class SpringAnimation extends Animation {
|
|
|
370
363
|
|
|
371
364
|
stop(): void {
|
|
372
365
|
super.stop();
|
|
373
|
-
this.__active = false;
|
|
374
366
|
clearTimeout(this._timeout);
|
|
375
|
-
|
|
376
|
-
|
|
367
|
+
if (this._animationFrame != null) {
|
|
368
|
+
global.cancelAnimationFrame(this._animationFrame);
|
|
369
|
+
}
|
|
370
|
+
this.__notifyAnimationEnd({finished: false});
|
|
377
371
|
}
|
|
378
372
|
}
|