Clean spot screen and CardComponent 🎨
continuous-integration/drone/push Build is passing
Details
Before Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 729 KiB |
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 2.6 MiB |
Before Width: | Height: | Size: 208 KiB |
Before Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 892 KiB |
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 1.6 MiB |
After Width: | Height: | Size: 247 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 915 B |
@ -1,6 +1,5 @@
|
|||||||
const Lotties = {
|
const Lotties = {
|
||||||
likeAnimation: require('./spotify-like-interaction.json')
|
likeAnimation: require('./spotify-like-interaction.json')
|
||||||
// riveLike : require('./light_like.riv'),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Lotties;
|
export default Lotties;
|
@ -1,227 +0,0 @@
|
|||||||
import { View, Image, Dimensions, StyleSheet } from 'react-native'
|
|
||||||
import React from 'react'
|
|
||||||
import Animated, { interpolate, runOnJS, useAnimatedGestureHandler, useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated';
|
|
||||||
import normalize from '../components/Normalize';
|
|
||||||
import { PanGestureHandler, PanGestureHandlerGestureEvent } from 'react-native-gesture-handler';
|
|
||||||
|
|
||||||
const SCREEN_WIDTH = Dimensions.get('window').width
|
|
||||||
const SCREEN_HEIGHT = Dimensions.get('window').height
|
|
||||||
|
|
||||||
interface CardProps {
|
|
||||||
title: string;
|
|
||||||
image: any;
|
|
||||||
onSwipe: (direction: "left" | "right" | "down") => void;
|
|
||||||
}
|
|
||||||
type ContextType = {
|
|
||||||
translateX: number;
|
|
||||||
translateY: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
const Card = ({ image, onSwipe }: CardProps) => {
|
|
||||||
|
|
||||||
const translateX = useSharedValue(0);
|
|
||||||
const translateY = useSharedValue(0);
|
|
||||||
const scale = useSharedValue(1);
|
|
||||||
const onGestureEvent = useAnimatedGestureHandler<
|
|
||||||
PanGestureHandlerGestureEvent,
|
|
||||||
ContextType
|
|
||||||
>({
|
|
||||||
onStart: (event, context) => {
|
|
||||||
context.translateX = translateX.value;
|
|
||||||
context.translateY = translateY.value;
|
|
||||||
},
|
|
||||||
onActive: (event, context) => {
|
|
||||||
translateX.value = event.translationX + context.translateX;
|
|
||||||
translateY.value = event.translationY + context.translateY;
|
|
||||||
|
|
||||||
},
|
|
||||||
onEnd: () => {
|
|
||||||
|
|
||||||
if (translateX.value > 160) {
|
|
||||||
console.log("translateX2");
|
|
||||||
runOnJS(onSwipe)("right");
|
|
||||||
} else if (translateX.value < -160) {
|
|
||||||
runOnJS(onSwipe)("left");
|
|
||||||
} else if (translateY.value > 250) {
|
|
||||||
runOnJS(onSwipe)("down");
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
translateX.value = withSpring(0);
|
|
||||||
translateY.value = withSpring(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
//better to have 2 listerner => 2 useAnimatedStyle ou faire une ftc qui retourne l'verse de une useAnimatedStyle
|
|
||||||
const opacLStyle = useAnimatedStyle(() => {
|
|
||||||
const opacityl = interpolate
|
|
||||||
(translateX.value,
|
|
||||||
[-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 4],
|
|
||||||
[0, 0, 1]);
|
|
||||||
return {
|
|
||||||
opacity: opacityl,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
const opacRStyle = useAnimatedStyle(() => {
|
|
||||||
const opacityl = interpolate
|
|
||||||
(translateX.value,
|
|
||||||
[-SCREEN_WIDTH / 4, 0, SCREEN_WIDTH / 2],
|
|
||||||
[1, 0, 0]);
|
|
||||||
return {
|
|
||||||
opacity: opacityl,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const opacCStyle = useAnimatedStyle(() => {
|
|
||||||
const opacityl = interpolate
|
|
||||||
(translateX.value,
|
|
||||||
[-SCREEN_WIDTH / 4, 0, SCREEN_WIDTH / 4],
|
|
||||||
[0.35, 0, 0.35]);
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
|
||||||
opacity: opacityl,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
const opacCStyle2 = useAnimatedStyle(() => {
|
|
||||||
const opacityl = interpolate
|
|
||||||
(translateY.value,
|
|
||||||
[0, SCREEN_HEIGHT / 4],
|
|
||||||
[0, 0.35]);
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
|
||||||
opacity: opacityl,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const opacDStyle = useAnimatedStyle(() => {
|
|
||||||
const opacityl = interpolate
|
|
||||||
(translateY.value,
|
|
||||||
[100, 300],
|
|
||||||
[0, 1]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
opacity: opacityl,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const horizontalThreshold = SCREEN_WIDTH * 0.65;
|
|
||||||
|
|
||||||
const styleCardsNew = useAnimatedStyle(() => {
|
|
||||||
const factor = 1;
|
|
||||||
const rot = interpolate
|
|
||||||
(translateX.value,
|
|
||||||
[0, factor * horizontalThreshold],
|
|
||||||
[0, 15],
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
transform: [
|
|
||||||
{ scale: scale.value },
|
|
||||||
{ translateX: translateX.value },
|
|
||||||
{ translateY: translateY.value },
|
|
||||||
{ rotateZ: `${rot}deg` },
|
|
||||||
]
|
|
||||||
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View>
|
|
||||||
<PanGestureHandler onGestureEvent={onGestureEvent}>
|
|
||||||
<Animated.View style={[styleCardsNew, styles.container]}>
|
|
||||||
<Animated.View style={[styles.image, {
|
|
||||||
backgroundColor: 'black', elevation: 100,
|
|
||||||
position: "absolute", borderWidth: 8, borderColor: '#FFF',
|
|
||||||
zIndex: 1000,
|
|
||||||
}, opacCStyle]}>
|
|
||||||
</Animated.View>
|
|
||||||
<Animated.View style={[styles.image, {
|
|
||||||
backgroundColor: 'black', elevation: 100,
|
|
||||||
position: "absolute", borderWidth: 8, borderColor: '#FFF',
|
|
||||||
zIndex: 1000,
|
|
||||||
}, opacCStyle2]}>
|
|
||||||
</Animated.View>
|
|
||||||
<Image source={{ uri: image }} style={[styles.image]} />
|
|
||||||
<>
|
|
||||||
<Animated.View
|
|
||||||
style={[{
|
|
||||||
elevation: 100,
|
|
||||||
position: "absolute",
|
|
||||||
zIndex: 1000,
|
|
||||||
}, opacRStyle]}
|
|
||||||
>
|
|
||||||
<Image style={[{ alignSelf: "center" }]}
|
|
||||||
source={require('../assets/images/dislike_icon.png')}
|
|
||||||
/>
|
|
||||||
</Animated.View>
|
|
||||||
<Animated.View
|
|
||||||
style={[{
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
position: "absolute",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignContent: "center",
|
|
||||||
zIndex: 1000,
|
|
||||||
elevation: 100,
|
|
||||||
}, opacLStyle]}
|
|
||||||
>
|
|
||||||
<Image style={[{ alignSelf: "center" }]}
|
|
||||||
source={require('../assets/images/like_icon.png')}
|
|
||||||
|
|
||||||
/>
|
|
||||||
</Animated.View>
|
|
||||||
<Animated.View
|
|
||||||
style={[{
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
position: "absolute",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignContent: "center",
|
|
||||||
elevation: 100,
|
|
||||||
zIndex: 1000,
|
|
||||||
}, opacDStyle]}
|
|
||||||
>
|
|
||||||
<Image style={[{
|
|
||||||
alignSelf: "center", width: 126.27,
|
|
||||||
height: 118.64,
|
|
||||||
}]}
|
|
||||||
source={require('../assets/images/discovery_icon.png')}
|
|
||||||
|
|
||||||
/>
|
|
||||||
</Animated.View>
|
|
||||||
</>
|
|
||||||
|
|
||||||
</Animated.View>
|
|
||||||
</PanGestureHandler>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
card: {
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center',
|
|
||||||
},
|
|
||||||
image: {
|
|
||||||
borderRadius: 24,
|
|
||||||
resizeMode: 'stretch',
|
|
||||||
height: normalize(420),
|
|
||||||
width: normalize(420),
|
|
||||||
},
|
|
||||||
container: {
|
|
||||||
flex: 1,
|
|
||||||
width: '100%',
|
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
export default Card;
|
|
||||||
|
|
@ -0,0 +1,212 @@
|
|||||||
|
import { View, Image, Dimensions, StyleSheet } from 'react-native'
|
||||||
|
import React from 'react'
|
||||||
|
import Animated, { interpolate, runOnJS, useAnimatedGestureHandler, useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated';
|
||||||
|
import normalize from './Normalize';
|
||||||
|
import { PanGestureHandler, PanGestureHandlerGestureEvent } from 'react-native-gesture-handler';
|
||||||
|
|
||||||
|
const SCREEN_WIDTH = Dimensions.get('window').width;
|
||||||
|
const SCREEN_HEIGHT = Dimensions.get('window').height;
|
||||||
|
|
||||||
|
interface CardProps {
|
||||||
|
image: any;
|
||||||
|
onSwipe: (direction: "left" | "right" | "down") => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContextType = {
|
||||||
|
translateX: number;
|
||||||
|
translateY: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function CardComponent(props: CardProps) {
|
||||||
|
|
||||||
|
const translateX = useSharedValue(0);
|
||||||
|
const translateY = useSharedValue(0);
|
||||||
|
const scale = useSharedValue(1);
|
||||||
|
const onGestureEvent = useAnimatedGestureHandler<
|
||||||
|
PanGestureHandlerGestureEvent,
|
||||||
|
ContextType
|
||||||
|
>({
|
||||||
|
onStart: (event, context) => {
|
||||||
|
context.translateX = translateX.value;
|
||||||
|
context.translateY = translateY.value;
|
||||||
|
},
|
||||||
|
onActive: (event, context) => {
|
||||||
|
translateX.value = event.translationX + context.translateX;
|
||||||
|
translateY.value = event.translationY + context.translateY;
|
||||||
|
},
|
||||||
|
onEnd: () => {
|
||||||
|
|
||||||
|
if (translateX.value > SCREEN_WIDTH / 2) {
|
||||||
|
runOnJS(props.onSwipe)("right");
|
||||||
|
} else if (translateX.value < -SCREEN_WIDTH / 2) {
|
||||||
|
runOnJS(props.onSwipe)("left");
|
||||||
|
} else if (translateY.value > SCREEN_HEIGHT / 2) {
|
||||||
|
runOnJS(props.onSwipe)("down");
|
||||||
|
} else {
|
||||||
|
translateX.value = withSpring(0);
|
||||||
|
translateY.value = withSpring(0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const opacityRightIcon = useAnimatedStyle(() => {
|
||||||
|
const horizontal = interpolate
|
||||||
|
(translateX.value,
|
||||||
|
[-SCREEN_WIDTH / 4, 20, SCREEN_WIDTH / 4],
|
||||||
|
[0, 0, 1]);
|
||||||
|
|
||||||
|
const vertical = interpolate
|
||||||
|
(translateY.value,
|
||||||
|
[20, SCREEN_HEIGHT / 4],
|
||||||
|
[1, 0.2]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
opacity: horizontal * vertical,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const opacityLeftIcon = useAnimatedStyle(() => {
|
||||||
|
const horizontal = interpolate
|
||||||
|
(translateX.value,
|
||||||
|
[-SCREEN_WIDTH / 4, -20, SCREEN_WIDTH / 4],
|
||||||
|
[1, 0, 0]);
|
||||||
|
|
||||||
|
const vertical = interpolate
|
||||||
|
(translateY.value,
|
||||||
|
[20, SCREEN_HEIGHT / 4],
|
||||||
|
[1, 0.2]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
opacity: horizontal * vertical,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const opacityDownIcon = useAnimatedStyle(() => {
|
||||||
|
const vertical = interpolate
|
||||||
|
(translateY.value,
|
||||||
|
[20, SCREEN_HEIGHT / 2],
|
||||||
|
[0, 1]);
|
||||||
|
|
||||||
|
const horizontal = interpolate
|
||||||
|
(translateX.value,
|
||||||
|
[-SCREEN_WIDTH / 4, 0, SCREEN_WIDTH / 4],
|
||||||
|
[0.5, 1, 0.5]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
opacity: vertical * horizontal,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const opacityHorizontalBackground = useAnimatedStyle(() => {
|
||||||
|
const value = interpolate
|
||||||
|
(translateX.value,
|
||||||
|
[-SCREEN_WIDTH / 4, 0, SCREEN_WIDTH / 4],
|
||||||
|
[0.27, 0, 0.27]);
|
||||||
|
return {
|
||||||
|
opacity: value,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const opacityDownBackground = useAnimatedStyle(() => {
|
||||||
|
const value = interpolate
|
||||||
|
(translateY.value,
|
||||||
|
[0, SCREEN_HEIGHT / 5],
|
||||||
|
[0, 0.28]);
|
||||||
|
return {
|
||||||
|
opacity: value,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const horizontalThreshold = SCREEN_WIDTH * 0.65;
|
||||||
|
|
||||||
|
const styleCardsNew = useAnimatedStyle(() => {
|
||||||
|
const factor = 1;
|
||||||
|
const rot = interpolate
|
||||||
|
(translateX.value,
|
||||||
|
[0, factor * horizontalThreshold],
|
||||||
|
[0, 15],
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
transform: [
|
||||||
|
{ scale: scale.value },
|
||||||
|
{ translateX: translateX.value },
|
||||||
|
{ translateY: translateY.value },
|
||||||
|
{ rotateZ: `${rot}deg` },
|
||||||
|
]
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<PanGestureHandler onGestureEvent={onGestureEvent}>
|
||||||
|
<Animated.View style={[styleCardsNew, styles.container]}>
|
||||||
|
<Animated.View style={[styles.image, styles.backgroundEffect, opacityHorizontalBackground]} />
|
||||||
|
<Animated.View style={[styles.image, styles.backgroundEffect, opacityDownBackground]} />
|
||||||
|
<Image source={{ uri: props.image }} style={[styles.image]} />
|
||||||
|
<Animated.View style={[styles.iconContainer, opacityLeftIcon]}>
|
||||||
|
<Image style={{ alignSelf: "center" }}
|
||||||
|
source={require('../assets/images/dislike_icon.png')}
|
||||||
|
/>
|
||||||
|
</Animated.View>
|
||||||
|
<Animated.View style={[styles.iconContainer, opacityRightIcon]} >
|
||||||
|
<Image style={{ alignSelf: "center" }}
|
||||||
|
source={require('../assets/images/like_icon.png')}
|
||||||
|
/>
|
||||||
|
</Animated.View>
|
||||||
|
<Animated.View style={[styles.iconContainer, opacityDownIcon]}>
|
||||||
|
<Image style={styles.icon}
|
||||||
|
source={require('../assets/images/discovery_icon.png')}
|
||||||
|
/>
|
||||||
|
</Animated.View>
|
||||||
|
</Animated.View>
|
||||||
|
</PanGestureHandler>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
image: {
|
||||||
|
borderRadius: 24,
|
||||||
|
resizeMode: 'stretch',
|
||||||
|
height: normalize(420),
|
||||||
|
width: normalize(420),
|
||||||
|
},
|
||||||
|
backgroundEffect: {
|
||||||
|
backgroundColor: 'black',
|
||||||
|
elevation: 100,
|
||||||
|
position: "absolute",
|
||||||
|
borderWidth: 8,
|
||||||
|
borderColor: '#FFF',
|
||||||
|
zIndex: 1
|
||||||
|
},
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
width: '100%',
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
shadowColor: "#000",
|
||||||
|
shadowOffset: {
|
||||||
|
width: 0,
|
||||||
|
height: 4,
|
||||||
|
},
|
||||||
|
shadowOpacity: 0.39,
|
||||||
|
shadowRadius: 8.30,
|
||||||
|
},
|
||||||
|
iconContainer: {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
position: "absolute",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
elevation: 100,
|
||||||
|
zIndex: 1
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
alignSelf: "center",
|
||||||
|
width: 126.27,
|
||||||
|
height: 118.64,
|
||||||
|
}
|
||||||
|
});
|
@ -1,5 +1,5 @@
|
|||||||
import Music from "../models/Music";
|
import Music from "../../models/Music";
|
||||||
import IMusicService from "./musics/interfaces/IMusicService";
|
import IMusicService from "./interfaces/IMusicService";
|
||||||
|
|
||||||
export default class EmptyMusicService implements IMusicService {
|
export default class EmptyMusicService implements IMusicService {
|
||||||
getImageArtistWithId(idArtist: string): Promise<string | null> {
|
getImageArtistWithId(idArtist: string): Promise<string | null> {
|