[REF] InteractiveBase refactoring logic
This commit is contained in:
143
front/components/UI/InteractiveCC.tsx
Normal file
143
front/components/UI/InteractiveCC.tsx
Normal file
@@ -0,0 +1,143 @@
|
||||
import React, { useRef, useEffect } from 'react';
|
||||
import { Animated, StyleSheet, Pressable, ViewStyle, StyleProp } from 'react-native';
|
||||
|
||||
type StyleObject = Record<string, any>;
|
||||
type InterpolatedStyleObject = Record<string, Animated.AnimatedInterpolation<any>>;
|
||||
|
||||
interface InteractiveCCProps {
|
||||
defaultStyle: StyleObject;
|
||||
hoverStyle: StyleObject;
|
||||
pressStyle: StyleObject;
|
||||
duration?: number;
|
||||
children?: React.ReactNode;
|
||||
onPress?: () => void | Promise<void>;
|
||||
isDisabled?: boolean;
|
||||
style?: StyleProp<ViewStyle>;
|
||||
styleContainer?: StyleProp<ViewStyle>;
|
||||
}
|
||||
|
||||
const InteractiveCC: React.FC<InteractiveCCProps> = ({ defaultStyle, hoverStyle, pressStyle, children, onPress, isDisabled, style, styleContainer, duration=250 }) => {
|
||||
const animatedValues = useRef<Record<string, Animated.Value>>({}).current;
|
||||
|
||||
const extractTransformKeys = (styleObject: StyleObject) => {
|
||||
const transformKeys = styleObject.transform ? styleObject.transform.map((t: any) => Object.keys(t)[0]) : [];
|
||||
return transformKeys;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// Initialisez les valeurs animées pour les propriétés de style non-transform
|
||||
const allStyleKeys = new Set([
|
||||
...Object.keys(defaultStyle),
|
||||
...Object.keys(hoverStyle),
|
||||
...Object.keys(pressStyle),
|
||||
]);
|
||||
|
||||
allStyleKeys.forEach(key => {
|
||||
if (!animatedValues[key]) {
|
||||
animatedValues[key] = new Animated.Value(0);
|
||||
}
|
||||
});
|
||||
// Initialisez les valeurs animées pour les propriétés de style transform
|
||||
const allTransformKeys = new Set([
|
||||
...extractTransformKeys(defaultStyle),
|
||||
...extractTransformKeys(hoverStyle),
|
||||
...extractTransformKeys(pressStyle),
|
||||
]);
|
||||
|
||||
allTransformKeys.forEach(key => {
|
||||
if (!animatedValues[key]) {
|
||||
animatedValues[key] = new Animated.Value(0);
|
||||
}
|
||||
});
|
||||
}, [defaultStyle, hoverStyle, pressStyle]);
|
||||
|
||||
const getTransformValue = (key: string, style: StyleObject) => {
|
||||
const transformObject = style.transform?.find((t: any) => t.hasOwnProperty(key));
|
||||
return transformObject ? transformObject[key] : 0;
|
||||
};
|
||||
|
||||
const interpolateStyle = (stateStyle: StyleObject, stateValue: number): InterpolatedStyleObject => {
|
||||
const interpolatedStyle: InterpolatedStyleObject = { ...stateStyle };
|
||||
const transform: any = [];
|
||||
|
||||
Object.keys(animatedValues).forEach(key => {
|
||||
if (stateStyle.transform?.some((t: any) => t.hasOwnProperty(key))) {
|
||||
// Interpolation des transformations
|
||||
const defaultValue = getTransformValue(key, defaultStyle);
|
||||
const hoverValue = getTransformValue(key, hoverStyle);
|
||||
const pressValue = getTransformValue(key, pressStyle);
|
||||
|
||||
const interpolated = animatedValues[key].interpolate({
|
||||
inputRange: [0, 1, 2],
|
||||
outputRange: [defaultValue, hoverValue, pressValue],
|
||||
});
|
||||
|
||||
transform.push({ [key]: interpolated });
|
||||
} else if (stateStyle[key]) {
|
||||
// Interpolation des autres styles
|
||||
const defaultValue = defaultStyle[key] || 0;
|
||||
const hoverValue = hoverStyle[key] !== undefined ? hoverStyle[key] : defaultValue;
|
||||
const pressValue = pressStyle[key] !== undefined ? pressStyle[key] : defaultValue;
|
||||
|
||||
interpolatedStyle[key] = animatedValues[key].interpolate({
|
||||
inputRange: [0, 1, 2],
|
||||
outputRange: [defaultValue, hoverValue, pressValue],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
interpolatedStyle.transform = transform;
|
||||
return interpolatedStyle;
|
||||
};
|
||||
|
||||
const animateToState = (stateValue: number) => {
|
||||
Object.keys(animatedValues).forEach(key => {
|
||||
Animated.timing(animatedValues[key], {
|
||||
toValue: stateValue,
|
||||
duration: duration,
|
||||
useNativeDriver: true, // Ajustez en fonction des propriétés animées
|
||||
}).start();
|
||||
});
|
||||
};
|
||||
|
||||
const handleMouseEnter = () => animateToState(1);
|
||||
const handlePressIn = () => animateToState(2);
|
||||
const handlePressOut = () => {
|
||||
animateToState(1);
|
||||
if (onPress && !isDisabled) {
|
||||
onPress();
|
||||
}
|
||||
};
|
||||
const handleMouseLeave = () => animateToState(0);
|
||||
|
||||
const animatedStyle = StyleSheet.flatten([
|
||||
styleContainer,
|
||||
interpolateStyle(defaultStyle, 0),
|
||||
interpolateStyle(hoverStyle, 1),
|
||||
interpolateStyle(pressStyle, 2),
|
||||
]);
|
||||
|
||||
return (
|
||||
<Animated.View style={animatedStyle}>
|
||||
<Pressable
|
||||
style={[styles.content, style]}
|
||||
focusable={false}
|
||||
onHoverIn={handleMouseEnter}
|
||||
onPressIn={handlePressIn}
|
||||
onPressOut={handlePressOut}
|
||||
onHoverOut={handleMouseLeave}
|
||||
>
|
||||
{children}
|
||||
</Pressable>
|
||||
</Animated.View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
content: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
});
|
||||
|
||||
export default InteractiveCC;
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Center, Text, useBreakpointValue, useTheme } from 'native-base';
|
||||
import { Center, Text, View, useBreakpointValue, useTheme } from 'native-base';
|
||||
import { useWindowDimensions } from 'react-native';
|
||||
import {
|
||||
TabView,
|
||||
@@ -19,6 +19,8 @@ import { useQueries, useQuery } from '../Queries';
|
||||
import API from '../API';
|
||||
import Song from '../models/Song';
|
||||
import { LoadingView } from '../components/Loading';
|
||||
import InteractiveCC from '../components/UI/InteractiveCC';
|
||||
import ButtonBase from '../components/UI/ButtonBase';
|
||||
|
||||
// Fichier de données fictives, par exemple MusicData.ts
|
||||
export const fakeMusicData = [
|
||||
@@ -1203,14 +1205,64 @@ export const FavoritesMusic = () => {
|
||||
},
|
||||
})) ?? [];
|
||||
|
||||
const { colors } = useTheme();
|
||||
|
||||
if (isLoading) {
|
||||
return <LoadingView />;
|
||||
}
|
||||
return (
|
||||
<MusicList
|
||||
initialMusics={musics}
|
||||
// musicsPerPage={7}
|
||||
/>
|
||||
<>
|
||||
<View style={{margin: 30}}>
|
||||
<InteractiveCC
|
||||
// duration={80}
|
||||
styleContainer={{
|
||||
width: 'fit-content',
|
||||
borderRadius: 10,
|
||||
}}
|
||||
style={{
|
||||
width: '100%',
|
||||
paddingHorizontal: 20,
|
||||
paddingVertical: 10,
|
||||
// borderRadius: 10,
|
||||
}}
|
||||
defaultStyle={{
|
||||
transform: [{ scale: 1,}],
|
||||
shadowOpacity: 0.3,
|
||||
shadowRadius: 4.65,
|
||||
elevation: 8,
|
||||
backgroundColor: colors.primary[300],
|
||||
}}
|
||||
hoverStyle={{
|
||||
transform: [{ scale: 1.02,}],
|
||||
shadowOpacity: 0.37,
|
||||
shadowRadius: 7.49,
|
||||
elevation: 12,
|
||||
backgroundColor: colors.primary[400],
|
||||
}}
|
||||
pressStyle={{
|
||||
transform: [{ scale: 0.98,}],
|
||||
shadowOpacity: 0.23,
|
||||
shadowRadius: 2.62,
|
||||
elevation: 4,
|
||||
backgroundColor: colors.primary[500],
|
||||
}}
|
||||
onPress={() => console.log("A que coucou!")}
|
||||
>
|
||||
<Text selectable={false} style={{color: '#fff'}}>
|
||||
Coucou
|
||||
</Text>
|
||||
</InteractiveCC>
|
||||
<ButtonBase
|
||||
title="Coucou"
|
||||
style={{ width: 'fit-content', marginTop: 20 }}
|
||||
type={'filled'}
|
||||
/>
|
||||
</View>
|
||||
<MusicList
|
||||
initialMusics={musics}
|
||||
// musicsPerPage={7}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user