Skip to content

Commit

Permalink
Fix layout animations that use custom animations changing colours (#5903
Browse files Browse the repository at this point in the history
)

## Summary

As stated in
#5826,
layout animation that had a custom animation inside (specifically,
`withDelay` that launched a `withTiming` that animates background colour
change) just wasn't properly working. Turned out, that we *****have
to***** pass values between colour animations as unprocessed rgba's
rather than processed numbers.

This PR fixes it and, of course, the issue as well.

## Test plan

You can try the following code (it is a cleaned version of snack given
in the mentioned issue):

<details><summary>Code</summary>

``` TYPESCRIPT
import { Text, SafeAreaView, StyleSheet, View } from 'react-native';
import {
  Gesture,
  GestureDetector,
  GestureHandlerRootView,
} from 'react-native-gesture-handler';
import Animated, {
  runOnJS,
  withDelay,
  withTiming,
} from 'react-native-reanimated';
import React, { useState } from 'react';

export default function EmptyExample() {
  const [myArray, setArray] = useState([1, 2, 3, 4, 5]);

  const customAnim = () => {
    'worklet';
    const animations = {
      backgroundColor: withDelay(
        500,
        withTiming('rgba(179, 6, 6, 1)', { duration: 500 })
      ),
    };
    const initialValues = { backgroundColor: 'rgba(16, 128, 26, 1)' };
    return { initialValues, animations };
  };

  const handleAddElement = Gesture.Tap().onStart(() => {
    runOnJS(setArray)([...myArray, Math.random().toString()]);
  });
  return (
    <SafeAreaView style={styles.container}>
      <GestureHandlerRootView>
        <GestureDetector gesture={handleAddElement}>
          <View>
            <Text>Add Element</Text>
          </View>
        </GestureDetector>
        {myArray.map((item) => {
          return (
            <Animated.View key={item.toString()} entering={customAnim}>
              <Text>{item}</Text>
            </Animated.View>
          );
        })}
      </GestureHandlerRootView>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
});

```
</details>
  • Loading branch information
szydlovsky authored Apr 25, 2024
1 parent e1eedbb commit ae12887
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 11 deletions.
1 change: 1 addition & 0 deletions app/src/examples/RuntimeTests/RuntimeTestsExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import './tests/animations/withTiming/easingSnapshots.test';
import './tests/animations/withTiming/basic.test';
import './tests/animations/withTiming/colors.test';
import './tests/animations/withTiming/arrays.test';
import './tests/animations/withTiming/enteringColorsSnapshots.test';

export default function RuntimeTestsExample() {
return <RuntimeTestsRunner />;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const AnimatedComponent = ({ easing }: { easing: EasingFunction | EasingFunction
);
};

async function getSnaphotUpdates(easingFn: EasingFunction | EasingFunctionFactory | undefined) {
async function getSnapshotUpdates(easingFn: EasingFunction | EasingFunctionFactory | undefined) {
await mockAnimationTimer();
const updatesContainer = await recordAnimationUpdates();
await render(<AnimatedComponent easing={easingFn} />);
Expand All @@ -54,7 +54,7 @@ async function getSnaphotUpdates(easingFn: EasingFunction | EasingFunctionFactor

describe('withTiming snapshots 📸, test EASING', () => {
test('No easing function', async () => {
const [updates, nativeUpdates] = await getSnaphotUpdates(undefined);
const [updates, nativeUpdates] = await getSnapshotUpdates(undefined);
expect(updates).toMatchSnapshots(Snapshots.noEasing);
expect(updates).toMatchNativeSnapshots(nativeUpdates, true);
});
Expand All @@ -79,7 +79,7 @@ describe('withTiming snapshots 📸, test EASING', () => {
.replace(/\./g, '$')
.replace(/-/g, '$')}`;

const [updates, nativeUpdates] = await getSnaphotUpdates(
const [updates, nativeUpdates] = await getSnapshotUpdates(
//@ts-ignore This error is because various easing functions accept different number of arguments
easing(...argumentSet),
);
Expand All @@ -97,13 +97,13 @@ describe('withTiming snapshots 📸, test EASING', () => {
Easing.quad,
Easing.sin,
])('Easing.%p', async easing => {
const [updates, nativeUpdates] = await getSnaphotUpdates(easing);
const [updates, nativeUpdates] = await getSnapshotUpdates(easing);
expect(updates).toMatchSnapshots(Snapshots[easing.name as keyof typeof Snapshots]);
expect(updates).toMatchNativeSnapshots(nativeUpdates, true);
});

test.each([(Easing.in, Easing.out, Easing.inOut)])('Easing.%p(Easing.elastic(10))', async easing => {
const [updates, nativeUpdates] = await getSnaphotUpdates(easing(Easing.elastic(10)));
const [updates, nativeUpdates] = await getSnapshotUpdates(easing(Easing.elastic(10)));
expect(updates).toMatchSnapshots(Snapshots[easing.name as keyof typeof Snapshots]);
expect(updates).toMatchNativeSnapshots(nativeUpdates, true);
});
Expand Down
Loading

0 comments on commit ae12887

Please sign in to comment.