Clean spot screen and CardComponent 🎨
continuous-integration/drone/push Build is passing Details

pull/19/head
Emre KARTAL 1 year ago
parent bc612f98dd
commit d389b58930

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 729 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 892 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

@ -92,7 +92,7 @@ class SpotifyController implements IController {
): Promise<Response | void> => {
let code = req.query.code;
let storedRedirectUri = req.cookies ? req.cookies[this.clientRedirect] : null;
var authOptions = {
let authOptions = {
method: 'POST',
url: this.API_URL,
data: qs.stringify({

@ -36,7 +36,7 @@ class LocationService {
const radlat2 = Math.PI * lat2 / 180;
const theta = lon1 - lon2;
const radtheta = Math.PI * theta / 180;
var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
let dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
if (dist > 1) {
dist = 1;

@ -4,7 +4,7 @@ import Token from '../models/Token';
export const createToken = (user: User): string => {
return jwt.sign({ id: user._id }, process.env.SECRET_JWT as jwt.Secret, {
expiresIn: '1d',
expiresIn: '15d',
});
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 915 B

@ -1,6 +1,5 @@
const Lotties = {
likeAnimation: require('./spotify-like-interaction.json')
// riveLike : require('./light_like.riv'),
}
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,
}
});

@ -4,8 +4,8 @@ import { useSelector } from 'react-redux';
import { colorsDark } from '../constants/colorsDark';
import { colorsLight } from '../constants/colorsLight';
import normalize from './Normalize';
import Music from '../model/Music';
import Artist from '../model/Artist';
import Music from '../models/Music';
import Artist from '../models/Artist';
type CardMusicProps = {
music: Music
@ -35,7 +35,6 @@ export default function CardMusic(props: CardMusicProps) {
width: '100%',
height: '100%',
borderRadius: 10
},
textContainer: {
flex: 1,

@ -32,7 +32,7 @@ export default function Loading() {
});
return (
<View style={{ justifyContent: 'center', alignItems: 'center' }}>
<View>
<Animated.View style={[{ backgroundColor: '#B40404', justifyContent: 'center', alignItems: 'center' }, breatheStyleSquare]}>
<Animated.Image source={require('../assets/images/icon.png')} style={[{ height: size, width: size, borderColor: '#fff', borderRadius: size / 2 }]} />
</Animated.View>

@ -1,4 +1,4 @@
import EmptyMusicService from "../services/EmptyMusicService";
import EmptyMusicService from "../services/musics/EmptyMusicService";
import IMusicService from "../services/musics/interfaces/IMusicService";
import SpotifyService from "../services/musics/spotify/SpotifyService";

@ -27,7 +27,6 @@
"expo-random": "~13.0.0",
"expo-secure-store": "~12.0.0",
"expo-splash-screen": "~0.17.5",
"lottie-react-native": "5.1.4",
"react": "18.1.0",
"react-dom": "18.1.0",
"react-native": "0.70.8",

@ -1,6 +1,5 @@
import { Spot } from "../../models/Spot";
import { spotTypes } from "../types/spotTypes";
import { userTypes } from "../types/userTypes";
export const setSpotList = (spotList: Spot[]) => {
return {

@ -1,6 +1,6 @@
import axios from "axios";
import configs from "../../constants/config";
import { setDarkMode, setErrorNetwork, setErrorUpdateMessage, userLogin } from "../actions/userActions";
import { setDarkMode, setErrorUpdateMessage, userLogin } from "../actions/userActions";
import * as SecureStore from 'expo-secure-store';
import { UserMapper } from "../../models/mapper/UserMapper";

@ -15,7 +15,6 @@ const DismissKeyboard = ({ children }) => (
)
export default function LoginScreen() {
const [sound, setSound] = useState<Audio.Sound>();
const [rememberMe, setRememberMe] = useState(false);
const navigation = useNavigation();
// @ts-ignore
@ -30,7 +29,6 @@ export default function LoginScreen() {
const { sound } = await Audio.Sound.createAsync(
require('../assets/sounds/click.mp3')
);
setSound(sound);
await sound.playAsync();
}

@ -17,7 +17,6 @@ const DismissKeyboard = ({ children }) => (
)
export default function RegisterScreen() {
const [sound, setSound] = useState<Audio.Sound>();
const navigation = useNavigation();
const [spotifyToken, setSpotifyToken] = useState();
const [username, setUsername] = useState('');
@ -33,7 +32,6 @@ export default function RegisterScreen() {
const { sound } = await Audio.Sound.createAsync(
require('../assets/sounds/click.mp3')
);
setSound(sound);
await sound.playAsync();
}
@ -91,7 +89,6 @@ export default function RegisterScreen() {
encodeURIComponent(redirectUri)
})
const {
access_token: access_token,
refresh_token: refresh_token,
} = result.params
setSpotifyToken(refresh_token)

@ -1,197 +1,200 @@
import { View, Text, Dimensions, StyleSheet, ImageBackground, Image, Pressable, TouchableOpacity, SafeAreaView } from 'react-native'
import React, { useCallback, useEffect, useRef, useState } from 'react'
import React, { useEffect, useState } from 'react'
import { LinearGradient } from 'expo-linear-gradient';
import * as Haptics from 'expo-haptics';
import Animated from 'react-native-reanimated';
import Card from '../components/Card';
import Card from '../components/CardComponent';
import normalize from '../components/Normalize';
import LottieView from 'lottie-react-native'
import Lotties from '../assets/lottie/Lottie';
import Loading from '../components/LoadingComponent';
import { useNavigation } from '@react-navigation/native';
import { useDispatch, useSelector } from 'react-redux';
import { Spot } from '../models/Spot';
import { removeFromSpotList, setSpotList } from '../redux/actions/spotActions';
import { removeFromSpotList } from '../redux/actions/spotActions';
import { MusicServiceProvider } from '../models/MusicServiceProvider';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import Artist from '../models/Artist';
export default function SpotScreen() {
//@ts-ignore
const spotReducer: Spot[] = useSelector(state => state.appReducer.spot)
const [cards, setCards] = useState<Spot[]>(spotReducer);
const [currentCard, setcurrentCard] = useState(cards[cards.length - 1]);
const [currentCard, setcurrentCard] = useState<Spot>(cards[cards.length - 1]);
const dispatch = useDispatch();
useEffect(() => {
setCards(spotReducer);
setcurrentCard(spotReducer[spotReducer.length - 1]);
}, [spotReducer]);
const onSwipe = (direction: 'left' | 'right' | 'down') => {
if (direction === 'right') {
addLike(currentCard);
dispatch(removeFromSpotList(currentCard));
} else if (direction === 'left') {
console.log('Swiped left');
removeSpots(currentCard);
dispatch(removeFromSpotList(currentCard));
}
else if (direction === 'down') {
MusicServiceProvider.musicService.addToPlaylist(currentCard.music.id);
removeSpots(currentCard);
dispatch(removeFromSpotList(currentCard));
}
};
const likeButtonref = useRef<LottieView>(null);
const onLike = useCallback(() => {
likeButtonref.current?.reset();
likeButtonref.current?.play(0, 55);
likeButtonref.current?.play(55, 0);
}, [])
const dispatch = useDispatch();
function addLike(spot: Spot) {
onLike();
//dispatch(addFavoritesMusic(spot.music))
dispatch(removeFromSpotList(spot));
}
function removeSpots(spot: Spot) {
dispatch(removeFromSpotList(spot));
}
function addMockSpots() {
//@ts-ignore
dispatch(setSpotList(spotsData))
}
const navigator = useNavigation();
const { width: wWidht } = Dimensions.get("window");
const { width: width } = Dimensions.get("window");
const hapti = (card: Spot) => {
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Heavy)
// @ts-ignore
navigator.navigate("Detail", { "music": card.music })
};
return (
const insets = useSafeAreaInsets();
const styles = StyleSheet.create({
background1: {
backgroundColor: 'black',
height: '100%',
width: '100%',
paddingTop: insets.top,
},
background2: {
justifyContent: 'center',
alignItems: 'center',
flex: 1,
backgroundColor: "#141414",
paddingTop: insets.top
},
posterBackground: {
width: "130%",
height: "130%",
justifyContent: "center",
alignItems: "center",
position: 'absolute',
left: "-40%",
top: "-20%"
},
gradient: {
position: "absolute",
top: 0,
left: 0,
right: 0,
height: insets.top + 150,
},
titleLabel: {
fontStyle: 'normal',
left: width / 9,
top: '5%',
color: "#FFFFFF",
fontSize: normalize(40),
fontWeight: "800",
},
artistLabel: {
fontStyle: 'normal',
left: width / 9,
top: '5%',
color: "#FFFFFF",
fontSize: normalize(20),
},
buttonSection: {
flexDirection: 'row',
justifyContent: "space-evenly",
paddingHorizontal: 30,
width: '100%',
position: "absolute",
top: "74%"
},
button: {
alignItems: 'center',
borderRadius: 100,
justifyContent: 'center',
width: 61,
height: 61,
backgroundColor: '#24243A',
opacity: 0.8
},
dislikeIcon: {
resizeMode: "stretch",
height: '44%',
aspectRatio: 1.05,
},
discoveryIcon: {
resizeMode: "stretch",
height: '50%',
aspectRatio: 1.5,
marginLeft: '7%'
},
likeIcon: {
resizeMode: "stretch",
height: '50%',
aspectRatio: 1.1
},
loading: {
position: 'absolute',
paddingBottom: 50
},
explanation: {
color: "grey",
fontSize: 13,
fontWeight: "400",
textAlign: "center",
marginTop: 150
}
});
return (
<>
{cards.length > 0 ? (
<>
<ImageBackground blurRadius={7}
style={{
position: 'absolute',
width: "100%",
height: "100%",
justifyContent: "center",
alignItems: "center",
}}
<SafeAreaView style={styles.background1}>
<ImageBackground blurRadius={5}
style={styles.posterBackground}
source={{
uri: currentCard.music.cover,
}}
></ImageBackground>
<SafeAreaView style={styles.mainSafeArea}>
<LinearGradient colors={['rgba(2, 2, 2, 0.58) 0%', 'rgba(0, 0, 0, 0) 100.56%']} style={styles.gradient}>
<Text
style={{
fontStyle: 'normal',
left: wWidht / 9,
top: normalize(87),
color: "#FFFFFF",
fontSize: normalize(40),
fontWeight: "800",
}}>{currentCard.music.name}</Text>
<Text
/>
<LinearGradient colors={['rgba(2, 2, 2, 0.40) 0%', 'rgba(0, 0, 0, 0) 100%']} style={styles.gradient} />
<Text style={styles.titleLabel}>{currentCard.music.name}</Text>
<Text style={styles.artistLabel}>{currentCard.music.artists.map((artist: Artist) => artist.name).join(', ')}</Text>
<View style={{ flex: 0.7, justifyContent: 'center', alignItems: 'center' }}>
{cards.map((card, index) => (
<View
key={index}
style={{
fontStyle: 'normal',
left: wWidht / 9,
top: normalize(87),
color: "#FFFFFF",
fontSize: normalize(20),
}}>{currentCard.music.artists[0].name}</Text>
</LinearGradient>
</SafeAreaView>
<View style={{ flex: 8.35 }}>
<View style={{ flex: 1.83, justifyContent: 'center', alignItems: 'center' }}>
{cards.map((card) => (
<View style={{ position: 'absolute' }} >
<Pressable onLongPress={() => { hapti(card) }} >
<Card
title={card.music.name}
image={card.music.cover}
onSwipe={(direction) => { onSwipe(direction) }}
/>
</Pressable>
</View>
))
}
</View>
<View style={{ flex: 1, flexDirection: 'row', alignItems: "flex-start", justifyContent: 'center' }}>
<Animated.View style={{ flexDirection: 'row', width: '92%', alignItems: "center", justifyContent: 'space-evenly' }}>
<TouchableOpacity style={styles.button} onPress={() => onSwipe('left')}>
<Image source={require("../assets/images/dislike_icon_no_text.png")} style={{ width: '45%', height: '40%' }} />
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={() => onSwipe('down')}>
<Image source={require("../assets/images/discovery_icon_no_text.png")} style={{ width: '58%', height: '50%', marginLeft: '7%' }} />
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={() => onSwipe('right')}>
<LottieView autoPlay={false} loop={false} ref={likeButtonref} speed={2} source={Lotties.likeAnimation} style={styles.lottie} />
</TouchableOpacity>
</Animated.View>
</View>
position: 'absolute',
}}
>
<Pressable onLongPress={() => hapti(card)}>
<Card
image={card.music.cover}
onSwipe={(direction) => onSwipe(direction)}
/>
</Pressable>
</View>
))}
</View>
<View style={styles.buttonSection}>
<TouchableOpacity style={styles.button} onPress={() => onSwipe('left')}>
<Image source={require("../assets/images/dislike_icon_no_text.png")} style={styles.dislikeIcon} />
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={() => onSwipe('down')}>
<Image source={require("../assets/images/discovery_icon_no_text.png")} style={styles.discoveryIcon} />
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={() => onSwipe('right')}>
<Image source={require("../assets/images/like_icon_no_text.png")} style={styles.likeIcon} />
</TouchableOpacity>
</View>
</>
</SafeAreaView>
)
: (<View style={{ justifyContent: 'center', alignItems: 'center', flex: 1, backgroundColor: "#141414" }}>
<View style={{ position: "absolute" }}>
: (<SafeAreaView style={styles.background2}>
<View style={styles.loading}>
<Loading />
</View>
<Text style={{ color: "grey", fontWeight: "400", textAlign: "center", top: "10%" }}>Vous avez explorer toutes les spot autour de vous.
<Text style={styles.explanation}>Vous avez explorer toutes les spot autour de vous.
{"\n"}Continuer dans discoverie pour découvrir de nouvelles music basées sur vos gouts musicaux.</Text>
</View>)
</SafeAreaView>)
}
</>
);
};
const styles = StyleSheet.create({
mainSafeArea: {
flex: 1,
},
spot: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
alignContent: 'center',
flexDirection: 'column',
backgroundColor: '#000'
},
lottie: {
width: '100%',
},
button: {
setOpacityTo: 0.8,
alignItems: 'center',
borderRadius: 100,
justifyContent: 'center',
width: 61,
height: 61,
backgroundColor: '#24243A',
opacity: 0.8,
shadowRadius: 2,
},
gradient: {
position: "absolute",
top: 0,
left: 0,
right: 0,
height: 209,
},
})

@ -1,5 +1,5 @@
import Music from "../models/Music";
import IMusicService from "./musics/interfaces/IMusicService";
import Music from "../../models/Music";
import IMusicService from "./interfaces/IMusicService";
export default class EmptyMusicService implements IMusicService {
getImageArtistWithId(idArtist: string): Promise<string | null> {

@ -61,7 +61,7 @@ export default class SpotifyService implements IMusicService {
async getMusicsWithIds(ids: string[]): Promise<Music[]> {
const access_token = await this._token.getAccessToken();
var url = `${this.API_URL}/tracks?market=FR&ids=`;
let url = `${this.API_URL}/tracks?market=FR&ids=`;
if (ids.length == 0) {
return [];
}
@ -122,7 +122,7 @@ export default class SpotifyService implements IMusicService {
description: 'Retrouvez toutes vos découvertes faites sur FladMusic 🎵',
public: true
};
var headers = {
const headers = {
'Authorization': `Bearer ${access_token}`,
'Content-Type': 'application/json',
'Accept': 'application/json'
@ -132,20 +132,20 @@ export default class SpotifyService implements IMusicService {
return response.data.id;
}
async _isInPlaylist(idTrack: string, idPlaylist: string): Promise<Boolean> {
async _isInPlaylist(idTrack: string, idPlaylist: string): Promise<boolean> {
const access_token = await this._token.getAccessToken();
const response = await axios.get(`${this.API_URL}/playlists/${idPlaylist}/tracks?limit=100`, {
headers: {
'Authorization': `Bearer ${access_token}`
},
});
var nbTracks = response.data.items.filter((item: any) => item.track.id === idTrack).length;
const nbTracks = response.data.items.filter((item: any) => item.track.id === idTrack).length;
return (nbTracks >= 1) ? true : false;
}
async addToPlaylist(idTrack: string): Promise<void> {
var idPlaylist = await this._getPlaylistId();
const idPlaylist = await this._getPlaylistId();
if (await this._isInPlaylist(idTrack, idPlaylist)) {
return;

Loading…
Cancel
Save