|
|
@ -1,75 +1,101 @@
|
|
|
|
import { useNavigation } from "@react-navigation/native";
|
|
|
|
import { useIsFocused, useNavigation } from "@react-navigation/native";
|
|
|
|
import { View, Text, Image, StyleSheet, TouchableOpacity, ScrollView, Pressable, Share, Alert } from "react-native";
|
|
|
|
import { View, Text, Image, StyleSheet, TouchableOpacity, ScrollView, Share, Alert, SafeAreaView, Linking, FlatList, ActivityIndicator } from "react-native";
|
|
|
|
import Animated, { interpolate, SensorType, useAnimatedSensor, useAnimatedStyle, withSpring } from "react-native-reanimated";
|
|
|
|
import Animated, { interpolate, SensorType, useAnimatedSensor, useAnimatedStyle, withSpring } from "react-native-reanimated";
|
|
|
|
import { Audio } from 'expo-av';
|
|
|
|
import { Audio } from 'expo-av';
|
|
|
|
import { useEffect, useState } from "react";
|
|
|
|
import { useEffect, useState } from "react";
|
|
|
|
import normalize from '../components/Normalize';
|
|
|
|
import normalize from '../components/Normalize';
|
|
|
|
import Music from "../models/Music";
|
|
|
|
import Music from "../model/Music";
|
|
|
|
import { LinearGradient } from "expo-linear-gradient";
|
|
|
|
import { LinearGradient } from "expo-linear-gradient";
|
|
|
|
import { Feather as Icon } from "@expo/vector-icons";
|
|
|
|
import { MusicServiceProvider } from "../model/MusicServiceProvider";
|
|
|
|
import { MusicServiceProvider } from "../models/MusicServiceProvider";
|
|
|
|
import { SimilarMusic } from "../components/SimilarMusicComponent";
|
|
|
|
import { HorizontalFlatList } from "../components/HorizontalFlatList";
|
|
|
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
|
|
import { LittleCard } from "../components/littleCard";
|
|
|
|
import Artist from "../model/Artist";
|
|
|
|
|
|
|
|
import { BlurView } from 'expo-blur';
|
|
|
|
|
|
|
|
|
|
|
|
const halfPi = Math.PI / 2;
|
|
|
|
const halfPi = Math.PI / 2;
|
|
|
|
|
|
|
|
|
|
|
|
//@ts-ignore
|
|
|
|
//@ts-ignore
|
|
|
|
export default function DetailScreen({ route }) {
|
|
|
|
export default function DetailScreen({ route }) {
|
|
|
|
const music: Music = route.params.music;
|
|
|
|
const item: Music = route.params.music;
|
|
|
|
const [currentspot] = useState(music);
|
|
|
|
|
|
|
|
const [simularMusic, setSimularMusic] = useState<Music[]>([]);
|
|
|
|
const [simularMusic, setSimularMusic] = useState<Music[]>([]);
|
|
|
|
|
|
|
|
const [artistImage, setArtistImage] = useState<string | null>(null);
|
|
|
|
const [isPlaying, setIsPlaying] = useState(false);
|
|
|
|
const [isPlaying, setIsPlaying] = useState(false);
|
|
|
|
const [sound, setSound] = useState(null);
|
|
|
|
const [addedToPlaylist, setAddedToPlaylist] = useState(false);
|
|
|
|
|
|
|
|
const [sound, setSound] = useState<Audio.Sound | null>();
|
|
|
|
|
|
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
|
|
|
|
|
|
|
|
const navigator = useNavigation();
|
|
|
|
const navigator = useNavigation();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
useEffect(() => {
|
|
|
|
getSimilarTrack();
|
|
|
|
getSimilarTrack();
|
|
|
|
|
|
|
|
getArtistImage();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (item.trackPreviewUrl) {
|
|
|
|
|
|
|
|
loadMusic();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
|
|
|
if (sound) {
|
|
|
|
|
|
|
|
sound.unloadAsync();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
}, []);
|
|
|
|
}, []);
|
|
|
|
const getSimilarTrack = async () => {
|
|
|
|
|
|
|
|
const simularMusic = await MusicServiceProvider.musicService.getSimilarTracks(currentspot.id);
|
|
|
|
const isFocused = useIsFocused();
|
|
|
|
setSimularMusic(simularMusic);
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
|
|
if (!isFocused && sound) {
|
|
|
|
|
|
|
|
sound.stopAsync();
|
|
|
|
|
|
|
|
setIsPlaying(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}, [isFocused]);
|
|
|
|
|
|
|
|
|
|
|
|
const handlePlaySound = async () => {
|
|
|
|
const loadMusic = async () => {
|
|
|
|
if (sound === null) {
|
|
|
|
const { sound } = await Audio.Sound.createAsync(
|
|
|
|
const { sound: newSound } = await Audio.Sound.createAsync(
|
|
|
|
{ uri: item.trackPreviewUrl },
|
|
|
|
{ uri: music.trackPreviewUrl },
|
|
|
|
{ shouldPlay: isPlaying },
|
|
|
|
{ shouldPlay: true }
|
|
|
|
onPlaybackStatusUpdate
|
|
|
|
);
|
|
|
|
);
|
|
|
|
//setSound(newSound);
|
|
|
|
setSound(sound);
|
|
|
|
setIsPlaying(true);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
const getArtistImage = async () => {
|
|
|
|
setIsPlaying(true);
|
|
|
|
const image = await MusicServiceProvider.musicService.getImageArtistWithId(item.artists[0].id);
|
|
|
|
//@ts-ignore
|
|
|
|
setArtistImage(image);
|
|
|
|
await sound.playAsync();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const handleStopSound = async () => {
|
|
|
|
const onPlaybackStatusUpdate = (status: any) => {
|
|
|
|
if (sound !== null) {
|
|
|
|
if (status.didJustFinish) {
|
|
|
|
setIsPlaying(false);
|
|
|
|
setIsPlaying(false);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//@ts-ignore
|
|
|
|
const play = async () => {
|
|
|
|
await sound.stopAsync();
|
|
|
|
if (sound) {
|
|
|
|
|
|
|
|
if (isPlaying) {
|
|
|
|
|
|
|
|
await sound.pauseAsync();
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
await sound.replayAsync();
|
|
|
|
|
|
|
|
await sound.playAsync();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
setIsPlaying(!isPlaying);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
|
|
return sound ? () => {
|
|
|
|
const getSimilarTrack = async () => {
|
|
|
|
console.log('Unloading Sound');
|
|
|
|
try {
|
|
|
|
//@ts-ignore
|
|
|
|
const simularMusic = await MusicServiceProvider.musicService.getSimilarTracks(item.id);
|
|
|
|
sound.unloadAsync();
|
|
|
|
setSimularMusic(simularMusic);
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
|
|
setLoading(false);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
: undefined;
|
|
|
|
|
|
|
|
}, [sound]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const onShare = async () => {
|
|
|
|
const onShare = async () => {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
const result = await Share.share({
|
|
|
|
await Share.share({
|
|
|
|
message:
|
|
|
|
message:
|
|
|
|
music.url,
|
|
|
|
item.url,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
} catch (error: any) {
|
|
|
|
} catch (error: any) {
|
|
|
|
Alert.alert(error.message);
|
|
|
|
Alert.alert(error.message);
|
|
|
@ -77,11 +103,12 @@ export default function DetailScreen({ route }) {
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const addToPlaylist = async () => {
|
|
|
|
const addToPlaylist = async () => {
|
|
|
|
MusicServiceProvider.musicService.addToPlaylist(music.id);
|
|
|
|
MusicServiceProvider.musicService.addToPlaylist(item.id);
|
|
|
|
|
|
|
|
setAddedToPlaylist(true);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const sensor = useAnimatedSensor(SensorType.ROTATION);
|
|
|
|
const sensor = useAnimatedSensor(SensorType.ROTATION);
|
|
|
|
const styleAniamatedImage = useAnimatedStyle(() => {
|
|
|
|
const styleAnimatedImage = useAnimatedStyle(() => {
|
|
|
|
const { pitch, roll } = sensor.sensor.value;
|
|
|
|
const { pitch, roll } = sensor.sensor.value;
|
|
|
|
const verticalAxis = interpolate(
|
|
|
|
const verticalAxis = interpolate(
|
|
|
|
pitch,
|
|
|
|
pitch,
|
|
|
@ -99,127 +126,254 @@ export default function DetailScreen({ route }) {
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const insets = useSafeAreaInsets();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const styles = StyleSheet.create({
|
|
|
|
|
|
|
|
mainSafeArea: {
|
|
|
|
|
|
|
|
height: '100%',
|
|
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
|
|
paddingTop: insets.top
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
backgroundSection: {
|
|
|
|
|
|
|
|
height: "100%",
|
|
|
|
|
|
|
|
width: "100%",
|
|
|
|
|
|
|
|
position: "absolute"
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
back_drop: {
|
|
|
|
|
|
|
|
height: "100%",
|
|
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
|
|
position: "absolute",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
gradientFade: {
|
|
|
|
|
|
|
|
height: "100%",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
card: {
|
|
|
|
|
|
|
|
alignItems: 'center'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
cardCover: {
|
|
|
|
|
|
|
|
width: normalize(390),
|
|
|
|
|
|
|
|
height: normalize(390),
|
|
|
|
|
|
|
|
borderRadius: 16,
|
|
|
|
|
|
|
|
resizeMode: 'stretch'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
section1: {
|
|
|
|
|
|
|
|
flexDirection: "row",
|
|
|
|
|
|
|
|
alignItems: "center",
|
|
|
|
|
|
|
|
justifyContent: "space-between",
|
|
|
|
|
|
|
|
marginHorizontal: "10%",
|
|
|
|
|
|
|
|
marginBottom: "4%",
|
|
|
|
|
|
|
|
marginTop: "5%"
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
section2: {
|
|
|
|
|
|
|
|
flex: 1
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
section3: {
|
|
|
|
|
|
|
|
flexDirection: "row",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
similarTitle: {
|
|
|
|
|
|
|
|
color: "#FFF",
|
|
|
|
|
|
|
|
paddingLeft: "8%",
|
|
|
|
|
|
|
|
fontSize: normalize(28),
|
|
|
|
|
|
|
|
fontWeight: "600",
|
|
|
|
|
|
|
|
paddingBottom: normalize(15)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
title: {
|
|
|
|
|
|
|
|
maxWidth: "90%",
|
|
|
|
|
|
|
|
fontSize: normalize(30),
|
|
|
|
|
|
|
|
fontWeight: "bold",
|
|
|
|
|
|
|
|
color: "white"
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
playButton: {
|
|
|
|
|
|
|
|
height: normalize(60),
|
|
|
|
|
|
|
|
width: normalize(60),
|
|
|
|
|
|
|
|
backgroundColor: "#E70E0E",
|
|
|
|
|
|
|
|
borderRadius: 30
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
imagePlayButton: {
|
|
|
|
|
|
|
|
width: normalize(40),
|
|
|
|
|
|
|
|
height: normalize(40)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
bodyPlayButton: {
|
|
|
|
|
|
|
|
flex: 1,
|
|
|
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
|
|
|
alignItems: 'center'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
artist: {
|
|
|
|
|
|
|
|
maxWidth: "40%",
|
|
|
|
|
|
|
|
fontWeight: "bold",
|
|
|
|
|
|
|
|
color: "white",
|
|
|
|
|
|
|
|
fontSize: normalize(17),
|
|
|
|
|
|
|
|
paddingLeft: normalize(5)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
date: {
|
|
|
|
|
|
|
|
fontWeight: "400",
|
|
|
|
|
|
|
|
color: "white",
|
|
|
|
|
|
|
|
fontSize: normalize(17)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
buttonArtist: {
|
|
|
|
|
|
|
|
flexDirection: "row",
|
|
|
|
|
|
|
|
alignItems: "center",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
saveButton: {
|
|
|
|
|
|
|
|
backgroundColor: '#3F3F3F',
|
|
|
|
|
|
|
|
width: normalize(180),
|
|
|
|
|
|
|
|
height: normalize(50),
|
|
|
|
|
|
|
|
padding: 10,
|
|
|
|
|
|
|
|
borderRadius: 8,
|
|
|
|
|
|
|
|
marginRight: normalize(10),
|
|
|
|
|
|
|
|
flexDirection: "row",
|
|
|
|
|
|
|
|
alignItems: "center"
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
shareButton: {
|
|
|
|
|
|
|
|
backgroundColor: '#3F3F3F',
|
|
|
|
|
|
|
|
width: normalize(180),
|
|
|
|
|
|
|
|
height: normalize(50),
|
|
|
|
|
|
|
|
marginLeft: normalize(10),
|
|
|
|
|
|
|
|
padding: 10,
|
|
|
|
|
|
|
|
borderRadius: 8,
|
|
|
|
|
|
|
|
flexDirection: "row",
|
|
|
|
|
|
|
|
alignItems: "center"
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
saveIcon: {
|
|
|
|
|
|
|
|
width: normalize(14.7),
|
|
|
|
|
|
|
|
height: normalize(21),
|
|
|
|
|
|
|
|
marginLeft: normalize(9)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
shareIcon: {
|
|
|
|
|
|
|
|
width: normalize(25),
|
|
|
|
|
|
|
|
height: normalize(25),
|
|
|
|
|
|
|
|
marginBottom: normalize(5)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
saveText: {
|
|
|
|
|
|
|
|
fontSize: normalize(11),
|
|
|
|
|
|
|
|
paddingLeft: normalize(9),
|
|
|
|
|
|
|
|
color: "white",
|
|
|
|
|
|
|
|
fontWeight: "bold"
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
shareText: {
|
|
|
|
|
|
|
|
fontSize: normalize(11),
|
|
|
|
|
|
|
|
paddingLeft: normalize(5),
|
|
|
|
|
|
|
|
color: "white",
|
|
|
|
|
|
|
|
fontWeight: "bold"
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
explicitImage: {
|
|
|
|
|
|
|
|
marginLeft: normalize(5),
|
|
|
|
|
|
|
|
width: normalize(16),
|
|
|
|
|
|
|
|
height: normalize(16)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
options: {
|
|
|
|
|
|
|
|
flexDirection: "row",
|
|
|
|
|
|
|
|
alignItems: "center",
|
|
|
|
|
|
|
|
paddingTop: normalize(15),
|
|
|
|
|
|
|
|
justifyContent: "center",
|
|
|
|
|
|
|
|
paddingHorizontal: normalize(20)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
overlay: {
|
|
|
|
|
|
|
|
...StyleSheet.absoluteFillObject,
|
|
|
|
|
|
|
|
backgroundColor: 'rgba(0, 0, 0, 0.1)',
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<View style={styles.body}>
|
|
|
|
<View>
|
|
|
|
<View style={styles.backgroundSection}>
|
|
|
|
<View style={styles.backgroundSection}>
|
|
|
|
|
|
|
|
|
|
|
|
<Image
|
|
|
|
<Image
|
|
|
|
blurRadius={133}
|
|
|
|
|
|
|
|
style={styles.back_drop}
|
|
|
|
style={styles.back_drop}
|
|
|
|
source={{
|
|
|
|
source={{
|
|
|
|
uri: currentspot.cover,
|
|
|
|
uri: item.cover,
|
|
|
|
}}
|
|
|
|
}}
|
|
|
|
></Image>
|
|
|
|
/>
|
|
|
|
<LinearGradient style={styles.gradientFade}
|
|
|
|
<View style={styles.overlay} />
|
|
|
|
colors={['rgba(56,56,56,0)', 'rgba(14,14,14,1)']}>
|
|
|
|
<BlurView
|
|
|
|
</LinearGradient>
|
|
|
|
style={styles.gradientFade}
|
|
|
|
|
|
|
|
intensity={70}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<LinearGradient
|
|
|
|
|
|
|
|
colors={['rgba(56,0,56,0)', 'rgba(14,14,14,1)']}
|
|
|
|
|
|
|
|
style={styles.gradientFade}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</BlurView>
|
|
|
|
</View>
|
|
|
|
</View>
|
|
|
|
<View style={styles.background1}>
|
|
|
|
<SafeAreaView style={styles.mainSafeArea}>
|
|
|
|
<ScrollView style={styles.list} showsVerticalScrollIndicator={false} scrollEventThrottle={4}>
|
|
|
|
<ScrollView>
|
|
|
|
<View style={styles.section1}>
|
|
|
|
|
|
|
|
<View style={{ flex: 1, justifyContent: 'flex-start', alignItems: 'center' }}>
|
|
|
|
|
|
|
|
<View>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<Animated.Image
|
|
|
|
<View style={styles.card}>
|
|
|
|
source={{
|
|
|
|
<TouchableOpacity onPress={() => { Linking.openURL(item.url); }}>
|
|
|
|
uri: currentspot.cover,
|
|
|
|
<Animated.Image source={{ uri: item.cover }} style={[styles.cardCover, styleAnimatedImage]} />
|
|
|
|
}}
|
|
|
|
</TouchableOpacity>
|
|
|
|
style={[
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
width: normalize(429),
|
|
|
|
|
|
|
|
height: normalize(429),
|
|
|
|
|
|
|
|
borderRadius: 24,
|
|
|
|
|
|
|
|
resizeMode: 'stretch',
|
|
|
|
|
|
|
|
}, styleAniamatedImage
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
]}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</View>
|
|
|
|
</View>
|
|
|
|
<View style={{ marginTop: 45, flex: 1, flexDirection: 'row', }}>
|
|
|
|
<View style={styles.section1}>
|
|
|
|
<View>
|
|
|
|
<View style={styles.section2}>
|
|
|
|
|
|
|
|
<TouchableOpacity style={{ flexDirection: "row", alignItems: "center" }} onPress={() => { Linking.openURL(item.url); }}>
|
|
|
|
|
|
|
|
<Text numberOfLines={1} style={styles.title}>{item.name}</Text>
|
|
|
|
|
|
|
|
{item.explicit && (
|
|
|
|
|
|
|
|
<Image style={styles.explicitImage} source={require('../assets/images/explicit_icon.png')} />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
</TouchableOpacity>
|
|
|
|
|
|
|
|
<View style={styles.section3}>
|
|
|
|
|
|
|
|
<TouchableOpacity style={styles.buttonArtist} onPress={() => { Linking.openURL(item.artists[0].url); }}>
|
|
|
|
|
|
|
|
{artistImage && (
|
|
|
|
|
|
|
|
<Image style={{ width: normalize(30), height: normalize(30), borderRadius: 30 }} source={{ uri: artistImage }} />
|
|
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
<Text numberOfLines={1} style={styles.artist}>{item.artists.map((artist: Artist) => artist.name).join(', ')}</Text>
|
|
|
|
|
|
|
|
<Text style={styles.date}> - {item.date} - {Math.floor(item.duration / 60)} min {Math.floor(item.duration % 60)} s</Text>
|
|
|
|
|
|
|
|
</TouchableOpacity>
|
|
|
|
|
|
|
|
</View>
|
|
|
|
</View>
|
|
|
|
</View>
|
|
|
|
<TouchableOpacity activeOpacity={0.5} onPressIn={handlePlaySound}
|
|
|
|
|
|
|
|
onPressOut={handleStopSound} style={{
|
|
|
|
|
|
|
|
backgroundColor: '#F80404',
|
|
|
|
|
|
|
|
borderRadius: 100,
|
|
|
|
|
|
|
|
padding: normalize(23)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}}>
|
|
|
|
{item.trackPreviewUrl && (
|
|
|
|
<View style={{ flex: 1, justifyContent: 'center', alignContent: 'center' }}>
|
|
|
|
<TouchableOpacity style={styles.playButton} onPress={play}>
|
|
|
|
|
|
|
|
<View style={styles.bodyPlayButton}>
|
|
|
|
|
|
|
|
<Image style={styles.imagePlayButton} source={isPlaying ? require('../assets/images/play_icon.png') : require('../assets/images/pause_icon.png')} />
|
|
|
|
</View>
|
|
|
|
</View>
|
|
|
|
</TouchableOpacity>
|
|
|
|
</TouchableOpacity>
|
|
|
|
|
|
|
|
)}
|
|
|
|
</View>
|
|
|
|
</View>
|
|
|
|
|
|
|
|
<View style={styles.options}>
|
|
|
|
|
|
|
|
<TouchableOpacity onPress={addToPlaylist}>
|
|
|
|
|
|
|
|
<View style={styles.saveButton}>
|
|
|
|
|
|
|
|
<Image style={styles.saveIcon} source={addedToPlaylist ? require('../assets/images/save_icon_full.png') : require('../assets/images/save_icon.png')} />
|
|
|
|
|
|
|
|
<Text style={styles.saveText}>Dans ma collection</Text>
|
|
|
|
</View>
|
|
|
|
</View>
|
|
|
|
|
|
|
|
</TouchableOpacity>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<TouchableOpacity onPress={onShare}>
|
|
|
|
|
|
|
|
<View style={styles.shareButton}>
|
|
|
|
|
|
|
|
<Image style={styles.shareIcon} source={require('../assets/images/share_icon.png')} />
|
|
|
|
|
|
|
|
<Text style={styles.shareText}>Partager cette music</Text>
|
|
|
|
|
|
|
|
</View>
|
|
|
|
|
|
|
|
</TouchableOpacity>
|
|
|
|
</View>
|
|
|
|
</View>
|
|
|
|
|
|
|
|
|
|
|
|
<View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-evenly', width: '100%' }}>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<TouchableOpacity onPress={addToPlaylist} activeOpacity={0.6} style={{
|
|
|
|
|
|
|
|
flexDirection: 'row', justifyContent: 'space-evenly', alignItems: 'center', width: 180,
|
|
|
|
|
|
|
|
height: 64, borderRadius: 8, opacity: 0.86, backgroundColor: '#0B0606',
|
|
|
|
|
|
|
|
}}>
|
|
|
|
|
|
|
|
<Text style={{ fontSize: normalize(16), fontWeight: "700", color: '#FFFFFF' }}>Dans ma collection</Text>
|
|
|
|
|
|
|
|
</TouchableOpacity>
|
|
|
|
|
|
|
|
<TouchableOpacity onPress={onShare} activeOpacity={0.6} style={{
|
|
|
|
|
|
|
|
flexDirection: 'row', justifyContent: 'space-evenly', alignItems: 'center', width: 180,
|
|
|
|
|
|
|
|
height: 64, borderRadius: 8, opacity: 0.86, backgroundColor: '#0B0606',
|
|
|
|
|
|
|
|
}}>
|
|
|
|
|
|
|
|
<Icon name="share" size={24} color="#FFFF"></Icon>
|
|
|
|
|
|
|
|
{/* <FontAwesome name="bookmark" size={24} color="#FF0000" ></FontAwesome> */}
|
|
|
|
|
|
|
|
<Text style={{ fontSize: normalize(16), fontWeight: "700", color: '#FFFFFF' }}>Partager cette music</Text>
|
|
|
|
|
|
|
|
</TouchableOpacity>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</View>
|
|
|
|
<View style={{ paddingTop: normalize(25) }}>
|
|
|
|
{simularMusic.length !== 0 && (
|
|
|
|
<Text style={styles.similarTitle} >Similaire</Text>
|
|
|
|
<HorizontalFlatList title={'Similar'} data={simularMusic}>
|
|
|
|
{loading ? (
|
|
|
|
{(props) => (
|
|
|
|
<ActivityIndicator size="large" style={{ paddingTop: normalize(14) }} color="#FFF" />
|
|
|
|
<Pressable
|
|
|
|
) :
|
|
|
|
|
|
|
|
<FlatList
|
|
|
|
|
|
|
|
showsHorizontalScrollIndicator={false}
|
|
|
|
|
|
|
|
data={simularMusic}
|
|
|
|
|
|
|
|
horizontal={true}
|
|
|
|
|
|
|
|
keyExtractor={item => item.id}
|
|
|
|
|
|
|
|
renderItem={({ item }) =>
|
|
|
|
|
|
|
|
<TouchableOpacity
|
|
|
|
onPress={() => {
|
|
|
|
onPress={() => {
|
|
|
|
// @ts-ignore
|
|
|
|
// @ts-ignore
|
|
|
|
navigator.replace("Detail", { "music": props }) }} >
|
|
|
|
navigator.replace("Detail", { "music": item })
|
|
|
|
<LittleCard data={props} />
|
|
|
|
}} >
|
|
|
|
</Pressable>
|
|
|
|
<SimilarMusic music={item} />
|
|
|
|
)}
|
|
|
|
</TouchableOpacity>
|
|
|
|
</HorizontalFlatList>
|
|
|
|
}
|
|
|
|
)}
|
|
|
|
/>}
|
|
|
|
|
|
|
|
|
|
|
|
</ScrollView>
|
|
|
|
|
|
|
|
</View>
|
|
|
|
</View>
|
|
|
|
|
|
|
|
</ScrollView>
|
|
|
|
|
|
|
|
</SafeAreaView>
|
|
|
|
</View>
|
|
|
|
</View>
|
|
|
|
|
|
|
|
|
|
|
|
);
|
|
|
|
);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const styles = StyleSheet.create({
|
|
|
|
|
|
|
|
mainSafeArea: {
|
|
|
|
|
|
|
|
flex: 1,
|
|
|
|
|
|
|
|
backgroundColor: "#141414",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
body: {
|
|
|
|
|
|
|
|
backgroundColor: "#0E0E0E"
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
backgroundSection: {
|
|
|
|
|
|
|
|
height: "100%",
|
|
|
|
|
|
|
|
width: "100%",
|
|
|
|
|
|
|
|
position: "absolute"
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
back_drop: {
|
|
|
|
|
|
|
|
height: "160%",
|
|
|
|
|
|
|
|
width: '430%',
|
|
|
|
|
|
|
|
position: "absolute",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
gradientFade: {
|
|
|
|
|
|
|
|
height: "100%",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
background1: {
|
|
|
|
|
|
|
|
height: '100%',
|
|
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
list: {
|
|
|
|
|
|
|
|
height: "100%"
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
section1: {
|
|
|
|
|
|
|
|
paddingHorizontal: 25
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|