1 | 'use strict';
|
2 | import { withStyleAnimation } from '../animation/styleAnimation';
|
3 | import type { SharedValue } from '../commonTypes';
|
4 | import { makeUIMutable } from '../mutables';
|
5 | import { LayoutAnimationType } from './animationBuilder';
|
6 | import { runOnUIImmediately } from '../threads';
|
7 | import type {
|
8 | SharedTransitionAnimationsValues,
|
9 | LayoutAnimation,
|
10 | } from './animationBuilder/commonTypes';
|
11 |
|
12 | const TAG_OFFSET = 1e9;
|
13 |
|
14 | function startObservingProgress(
|
15 | tag: number,
|
16 | sharedValue: SharedValue<Record<string, unknown>>,
|
17 | animationType: LayoutAnimationType
|
18 | ): void {
|
19 | 'worklet';
|
20 | const isSharedTransition =
|
21 | animationType === LayoutAnimationType.SHARED_ELEMENT_TRANSITION;
|
22 | sharedValue.addListener(tag + TAG_OFFSET, () => {
|
23 | global._notifyAboutProgress(tag, sharedValue.value, isSharedTransition);
|
24 | });
|
25 | }
|
26 |
|
27 | function stopObservingProgress(
|
28 | tag: number,
|
29 | sharedValue: SharedValue<number>,
|
30 | removeView = false
|
31 | ): void {
|
32 | 'worklet';
|
33 | sharedValue.removeListener(tag + TAG_OFFSET);
|
34 | global._notifyAboutEnd(tag, removeView);
|
35 | }
|
36 |
|
37 | function createLayoutAnimationManager() {
|
38 | 'worklet';
|
39 | const currentAnimationForTag = new Map();
|
40 | const mutableValuesForTag = new Map();
|
41 |
|
42 | return {
|
43 | start(
|
44 | tag: number,
|
45 | type: LayoutAnimationType,
|
46 | |
47 |
|
48 |
|
49 | yogaValues: Partial<SharedTransitionAnimationsValues>,
|
50 | config: (
|
51 | arg: Partial<SharedTransitionAnimationsValues>
|
52 | ) => LayoutAnimation
|
53 | ) {
|
54 | if (type === LayoutAnimationType.SHARED_ELEMENT_TRANSITION_PROGRESS) {
|
55 | global.ProgressTransitionRegister.onTransitionStart(tag, yogaValues);
|
56 | return;
|
57 | }
|
58 |
|
59 | const style = config(yogaValues);
|
60 | let currentAnimation = style.animations;
|
61 |
|
62 |
|
63 |
|
64 | const previousAnimation = currentAnimationForTag.get(tag);
|
65 | if (previousAnimation) {
|
66 | currentAnimation = { ...previousAnimation, ...style.animations };
|
67 | }
|
68 | currentAnimationForTag.set(tag, currentAnimation);
|
69 |
|
70 | let value = mutableValuesForTag.get(tag);
|
71 | if (value === undefined) {
|
72 | value = makeUIMutable(style.initialValues);
|
73 | mutableValuesForTag.set(tag, value);
|
74 | } else {
|
75 | stopObservingProgress(tag, value);
|
76 | value._value = style.initialValues;
|
77 | }
|
78 |
|
79 |
|
80 | const animation = withStyleAnimation(currentAnimation);
|
81 |
|
82 | animation.callback = (finished?: boolean) => {
|
83 | if (finished) {
|
84 | currentAnimationForTag.delete(tag);
|
85 | mutableValuesForTag.delete(tag);
|
86 | const shouldRemoveView = type === LayoutAnimationType.EXITING;
|
87 | stopObservingProgress(tag, value, shouldRemoveView);
|
88 | }
|
89 | style.callback &&
|
90 | style.callback(finished === undefined ? false : finished);
|
91 | };
|
92 |
|
93 | startObservingProgress(tag, value, type);
|
94 | value.value = animation;
|
95 | },
|
96 | stop(tag: number) {
|
97 | const value = mutableValuesForTag.get(tag);
|
98 | if (!value) {
|
99 | return;
|
100 | }
|
101 | stopObservingProgress(tag, value);
|
102 | },
|
103 | };
|
104 | }
|
105 |
|
106 | runOnUIImmediately(() => {
|
107 | 'worklet';
|
108 | global.LayoutAnimationsManager = createLayoutAnimationManager();
|
109 | })();
|
110 |
|
111 | export type LayoutAnimationsManager = ReturnType<
|
112 | typeof createLayoutAnimationManager
|
113 | >;
|