MM-59973: fix the emoji count 0 issue when archive and unarchive chan… (#8146)
* MM-59973: fix the emoji count 0 issue when archive and unarchive channels * ref to null and initialing it * refactor: added a safe condition * refactor code * more clean up * clean-ups * index to tosting as a key to component * refactor code * fix: (MM-59973) emoji count 0 update (#8256) * reversed from all useMemo to useMemo + useEffect * tried to include everything into useMemo was an anti-pattern * moved back to useMemo + useEffect * previousNumber and animateToNumber comparison has some flaw when dealing with difference length between the two * simple fix * fix more silly mistakes * move _previousNumberString to constant * Test: increase timeout-minutes to 120 for e2e test * reverted the timeout-minutes back to 40 --------- Co-authored-by: Rahim Rahman <rahim.rahman@mattermost.com> Co-authored-by: Mattermost Build <build@mattermost.com>
This commit is contained in:
parent
8c7c02d298
commit
e4dc8dbbfe
1 changed files with 82 additions and 59 deletions
|
|
@ -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);
|
||||
|
|
@ -24,46 +24,73 @@ 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 animations = useMemo(() => {
|
||||
const animateToNumberArray = Array.from(animateToNumberString, Number);
|
||||
|
||||
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 * animateToNumberArray[index]),
|
||||
duration: animationDuration,
|
||||
useNativeDriver: true,
|
||||
easing: Easing.elastic(easing),
|
||||
}).start();
|
||||
});
|
||||
}, [
|
||||
animateToNumberString,
|
||||
animationDuration,
|
||||
animations,
|
||||
easing,
|
||||
numberHeight,
|
||||
]);
|
||||
|
||||
const setButtonLayout = useCallback((e: LayoutChangeEvent) => {
|
||||
setNumberHeight(e.nativeEvent.layout.height);
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
animations.forEach((animation, index) => {
|
||||
Animated.timing(animation, {
|
||||
toValue: -1 * (numberHeight * numberStringToDigitsArray[index]),
|
||||
duration: animationDuration || 1400,
|
||||
useNativeDriver: true,
|
||||
easing: easing || Easing.elastic(1.2),
|
||||
}).start();
|
||||
});
|
||||
}, [animateToNumber, animationDuration, fontStyle, numberHeight]);
|
||||
|
||||
const getTranslateY = (index: number) => {
|
||||
return animations[index];
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{numberHeight !== 0 && (
|
||||
|
|
@ -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 &&
|
||||
|
|
|
|||
Loading…
Reference in a new issue