Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MM-59973: fix the emoji count 0 issue when archive and unarchive chan… #8146

Merged
merged 12 commits into from
Oct 23, 2024
133 changes: 78 additions & 55 deletions app/components/animated_number/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import React, {useCallback, useMemo} from 'react';
import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {Animated, Easing, type LayoutChangeEvent, type StyleProp, Text, type TextStyle, View} from 'react-native';

interface Props {
animateToNumber: number;
fontStyle?: StyleProp<TextStyle>;
animationDuration?: number;
easing?: ((input: number) => number) | undefined;
easing?: number;
}

const NUMBERS = Array(10).fill(null).map((_, i) => i);
Expand All @@ -24,45 +24,72 @@ const usePrevious = (value: number) => {

const AnimatedNumber = ({
animateToNumber,
animationDuration,
animationDuration = 1400,
fontStyle,
easing,
easing = 1.2,
}: Props) => {
const prevNumber = usePrevious(animateToNumber);
const previousNumber = usePrevious(animateToNumber);
const [numberHeight, setNumberHeight] = useState(0);

const animateToNumberString = String(Math.abs(animateToNumber));
const prevNumberString = String(Math.abs(prevNumber));

const numberStringToDigitsArray = Array.from(animateToNumberString, Number);
const prevNumberersArr = Array.from(prevNumberString, Number);
const previousNumberString = useMemo(() => {
// comparing previousNumber and animateToNumber gets trickier when the number of digits changes and the length differs.
// By padding the previousNumber with 0s, or slicing the previousNumber to match the length of animateToNumber
// we can compare them digit by digit
const _previousNumberString = String(Math.abs(previousNumber)).padStart(
animateToNumberString.length,
'0',
);

const [numberHeight, setNumberHeight] = React.useState(0);
const animations = useMemo(() => numberStringToDigitsArray.map((__, index) => {
if (typeof prevNumberersArr[index] !== 'number') {
return new Animated.Value(0);
if (_previousNumberString.length > animateToNumberString.length) {
_previousNumberString.slice(_previousNumberString.length - animateToNumberString.length);
}

const animationHeight = -1 * (numberHeight * prevNumberersArr[index]);
return new Animated.Value(animationHeight);
}), [numberStringToDigitsArray]);
return _previousNumberString;
}, [animateToNumberString, previousNumber]);

const setButtonLayout = useCallback((e: LayoutChangeEvent) => {
setNumberHeight(e.nativeEvent.layout.height);
}, []);
const animations = useMemo(() => {
const animateToNumberArray = Array.from(animateToNumberString, Number);

React.useEffect(() => {
if (!numberHeight) {
return animateToNumberArray.map(() => new Animated.Value(0));
}

const previousNumberArray = Array.from(previousNumberString, Number);

return animateToNumberArray.map((_, index) => {
const useDigit = previousNumberArray[index] === animateToNumberArray[index] ? animateToNumberArray[index] : previousNumberArray[index];

return new Animated.Value(-1 * (numberHeight * useDigit));
});
}, [animateToNumberString, numberHeight, previousNumberString]);

useEffect(() => {
if (!numberHeight) {
return;
}

const animateToNumberArray = Array.from(animateToNumberString, Number);
animations.forEach((animation, index) => {
Animated.timing(animation, {
toValue: -1 * (numberHeight * numberStringToDigitsArray[index]),
duration: animationDuration || 1400,
toValue: -1 * (numberHeight * animateToNumberArray[index]),
duration: animationDuration,
rahimrahman marked this conversation as resolved.
Show resolved Hide resolved
useNativeDriver: true,
easing: easing || Easing.elastic(1.2),
easing: Easing.elastic(easing),
}).start();
});
}, [animateToNumber, animationDuration, fontStyle, numberHeight]);
}, [
animateToNumberString,
animationDuration,
animations,
easing,
numberHeight,
]);

const getTranslateY = (index: number) => {
return animations[index];
};
const setButtonLayout = useCallback((e: LayoutChangeEvent) => {
setNumberHeight(e.nativeEvent.layout.height);
}, []);

return (
<>
Expand All @@ -71,37 +98,33 @@ const AnimatedNumber = ({
{animateToNumber < 0 && (
<Text style={[fontStyle, {height: numberHeight}]}>{'-'}</Text>
)}
{numberStringToDigitsArray.map((n, index) => {
return (
<View
key={`${index.toString()}`}
style={{height: numberHeight, overflow: 'hidden'}}
>
<Animated.View
style={[
{Array.from(animateToNumberString, Number).map((_, index) => (
<View
key={`${animateToNumberString.length - index}`}
style={{height: numberHeight, overflow: 'hidden'}}
>
<Animated.View
style={{
transform: [
{
transform: [
{
translateY: getTranslateY(index),
},
],
translateY: animations[index],
},
]}
>
{NUMBERS.map((number, i) => (
<View
style={{flexDirection: 'row'}}
key={`${i.toString()}`}
>
<Text style={[fontStyle, {height: numberHeight}]}>
{number}
</Text>
</View>
))}
</Animated.View>
</View>
);
})}
],
}}
>
{NUMBERS.map((number, i) => (
<View
key={`${NUMBERS.length - i}`}
style={{flexDirection: 'row'}}
>
<Text style={[fontStyle, {height: numberHeight}]}>
{number}
</Text>
</View>
))}
</Animated.View>
</View>
))}
</View>
)}
{numberHeight === 0 &&
Expand Down