diff --git a/src/FLAD/Model/Artist.tsx b/src/FLAD/Model/Artist.tsx new file mode 100644 index 0000000..32e4151 --- /dev/null +++ b/src/FLAD/Model/Artist.tsx @@ -0,0 +1,12 @@ +export default class Artist { + private id : string; + private name : string; + private url : string; // Image.source + + constructor(id : string, name : string, url : string){ + this.id = id; + this.name = name; + this.url = url; + } + +} \ No newline at end of file diff --git a/src/FLAD/Model/factory/MusicFactory.ts b/src/FLAD/Model/factory/MusicFactory.ts index e1d9973..e26238b 100644 --- a/src/FLAD/Model/factory/MusicFactory.ts +++ b/src/FLAD/Model/factory/MusicFactory.ts @@ -11,4 +11,14 @@ export default class MusicFactory { ); return music; } + static mapFromSpotifyTrackSmpified(jsonMusic :any ): Music { + const music = new Music( + jsonMusic.id, + jsonMusic.name, + "", + jsonMusic.album.images[0].url, + jsonMusic.preview_url + ); + return music; + } } \ No newline at end of file diff --git a/src/FLAD/assets/icons/icons/icon.ts b/src/FLAD/assets/icons/icons/icon.ts index 670589c..c34f7bc 100644 --- a/src/FLAD/assets/icons/icons/icon.ts +++ b/src/FLAD/assets/icons/icons/icon.ts @@ -3,6 +3,8 @@ const Icons = { discovery: require('./icon_discovery.png'), like: require('./icon_like.png'), dislike: require('./icon_dislike.png'), + bookmark : require('./icon_bookmark.svg'), + share : require('./Vector.png'), // riveLike : require('./light_like.riv'), } diff --git a/src/FLAD/components/ArtistChip.tsx b/src/FLAD/components/ArtistChip.tsx new file mode 100644 index 0000000..5a7eb2f --- /dev/null +++ b/src/FLAD/components/ArtistChip.tsx @@ -0,0 +1,50 @@ +import { useCallback, useState } from 'react'; +import { View, StyleSheet ,Text,Image, Pressable, Linking, Alert} from 'react-native' + +interface ArtistChipProps { + backgroundColor : string; + artist : Artist; +} + +const ArtistChip = ({artist} : ArtistChipProps) => { + const handlePress = useCallback(async () => { + // Checking if the link is supported for links with custom URL scheme. + const supported = await Linking.canOpenURL(artist.url); + + if (supported) { + // Opening the link with some app, if the URL scheme is "http" the web link should be opened + // by some browser in the mobile + await Linking.openURL(artist.url); + } else { + Alert.alert(`Don't know how to open this URL: ${artist.url}`); + } + }, [artist.url]); + + return ( + + + + + + + + ii + + + + ); + }; + +const styles = StyleSheet.create({ + input : { + justifyContent : 'center', + alignItems : 'center', + placeholder : "placeholde" + }, +}) + +export default HalfCirlce; \ No newline at end of file diff --git a/src/FLAD/components/Genre.tsx b/src/FLAD/components/Genre.tsx index d1fdcb2..22f231d 100644 --- a/src/FLAD/components/Genre.tsx +++ b/src/FLAD/components/Genre.tsx @@ -78,6 +78,5 @@ export const ArtistLayout = () => { container: { flexDirection: "row", flexWrap: "wrap", - }, }); \ No newline at end of file diff --git a/src/FLAD/components/HorizontalFlatList.tsx b/src/FLAD/components/HorizontalFlatList.tsx index e14d26d..f701e38 100644 --- a/src/FLAD/components/HorizontalFlatList.tsx +++ b/src/FLAD/components/HorizontalFlatList.tsx @@ -12,15 +12,16 @@ import { Feather as Icon } from "@expo/vector-icons"; import Music from "../Model/Music"; import { State, TapGestureHandler } from "react-native-gesture-handler"; import { useRef, useState } from "react"; +import { RenderCellProps } from "./littleCard"; interface HorizontalFlatListProps { // React.ReactNode; - renderCell: (image: string, titre : string) => React.ReactElement + children:(props: RenderCellProps) => React.ReactElement title : string; data : any[]; } -export const HorizontalFlatList = ({ title, data, renderCell}: HorizontalFlatListProps) => { +export const HorizontalFlatList = ({ title, data, children : RenderCell }: HorizontalFlatListProps) => { return ( @@ -31,22 +32,19 @@ export const HorizontalFlatList = ({ title, data, renderCell}: HorizontalFlatLis data={data} horizontal={true} keyExtractor={item => item.id} - renderItem={({item}) =>{ - return renderCell(item.image, image.titre); - }} - /> + renderItem={({ item }) => RenderCell(item)}/> ); }; const styles = StyleSheet.create({ similarSection: { - paddingTop: 30 + paddingTop: 16 }, similarTitle: { - color: "#2998FD", - paddingLeft: 35, - fontSize: 17, + color: "#FFF", + paddingLeft: 8, + fontSize: 24, fontWeight: "600", - paddingBottom: 20 + paddingBottom: 16 } }); \ No newline at end of file diff --git a/src/FLAD/components/littleCard.tsx b/src/FLAD/components/littleCard.tsx index 362cd47..0b0e0d3 100644 --- a/src/FLAD/components/littleCard.tsx +++ b/src/FLAD/components/littleCard.tsx @@ -1,19 +1,23 @@ import {TouchableOpacity, ScrollView, View, Text, StyleSheet, Image, SafeAreaView, FlatList, Animated} from 'react-native'; - -export default function littleCard ({image,titre}){ +export interface RenderCellProps { + image: string; + title: string; + } +export const LittleCard = (props : RenderCellProps)=>{ + console.log('==============='+ props.image + props.title+ '==ok============'); return ( - - {titre} + + {props.title} ) } + const styles = StyleSheet.create({ similarContainer: { - width: 90, marginHorizontal: 7 }, similarTitleFilm: { @@ -22,8 +26,8 @@ const styles = StyleSheet.create({ fontWeight: "300" }, similarPoster: { - height: 130, - width: 90, - borderRadius: 8 + height: 160, + width: 160, + borderRadius: 16 } }) diff --git a/src/FLAD/data/data.ts b/src/FLAD/data/data.ts index 96fe6e1..bc3ee42 100644 --- a/src/FLAD/data/data.ts +++ b/src/FLAD/data/data.ts @@ -82,5 +82,24 @@ export const spotArray2: Spot[] = [ "Harry Styles", "https://i.scdn.co/image/ab67616d0000b2738900d48677696015bf325b8b", "https://p.scdn.co/mp3-preview/4fff3f8d76a422f42cea39f001836a3d54937fc4?cid=774b29d4f13844c495f206cafdad9c86") + ), + new Spot("6", new Music("30d0q6kt1BIfwAQUCAfxVQ", + "Calme toi", + "Kerchack", + "https://i.scdn.co/image/ab67616d0000b273b4f73fb5c5ea299c7ebfbf60", + "https://p.scdn.co/mp3-preview/5de1103b9528c1e47e03d32b0aa5dbfe797191a2?cid=774b29d4f13844c495f206cafdad9c86") + ), + new Spot("7", new Music("7IXQrRgmHxWYWitSlyFY7z", + "Peur (feat. Ziak)", + "Ziak", + "https://i.scdn.co/image/ab67616d0000b273b533a3a5625bc6ce1be56a2e", + "https://p.scdn.co/mp3-preview/2c613f31b11375980aba80a5b535bf87ddb6211b?cid=774b29d4f13844c495f206cafdad9c86") + ), + new Spot("8", new Music("7wBoSW48q4ZFe8qSdozqqi", + "Blue", + "Kerchack", + "https://i.scdn.co/image/ab67616d0000b273cc4e66af40292c9d92146909", + "https://p.scdn.co/mp3-preview/401b51374dd3f2a15466a0b415a9ac7d2114a54b?cid=774b29d4f13844c495f206cafdad9c86") ) + ]; diff --git a/src/FLAD/redux/actions/userActions.tsx b/src/FLAD/redux/actions/userActions.tsx index f470e84..2d43cc5 100644 --- a/src/FLAD/redux/actions/userActions.tsx +++ b/src/FLAD/redux/actions/userActions.tsx @@ -1,3 +1,4 @@ +import { User } from "../../Model/User"; import { userTypes } from "../types/userTypes"; @@ -31,12 +32,12 @@ export const restoreToken = (token : string) => { playload : token }; } -// export const UserLogin = (username: string, password: string) => { -// return { -// type: userTypes.LOGIN, -// playload : username, password -// }; -// } +export const userSignUp = (user : User) => { + return { + type: userTypes.LOGIN, + playload : user + }; + } export const UserLogout = () => { return { diff --git a/src/FLAD/redux/reducers/spotifyAuthReducer.tsx b/src/FLAD/redux/reducers/spotifyAuthReducer.tsx index 42effc8..dc241e7 100644 --- a/src/FLAD/redux/reducers/spotifyAuthReducer.tsx +++ b/src/FLAD/redux/reducers/spotifyAuthReducer.tsx @@ -5,7 +5,7 @@ String getApiRedirectUrl() => _api.identification.redirectUri; String getIdSpotify() => _currentUser.idSpotify; -String getIdDafl() => _currentUser.idDafl; +String getIdFlad() => _currentUser.idFlad; case getCompleteMusic diff --git a/src/FLAD/redux/thunk/authThunk.tsx b/src/FLAD/redux/thunk/authThunk.tsx index df93371..631ad33 100644 --- a/src/FLAD/redux/thunk/authThunk.tsx +++ b/src/FLAD/redux/thunk/authThunk.tsx @@ -4,7 +4,7 @@ import axios from "axios"; import { json } from "express"; import { useEffect } from "react"; import { API_URL } from "../../fladConfig"; -import { Credentials, CredentialsRegister, restoreToken, setLoginState } from "../actions/userActions"; +import { Credentials, CredentialsRegister, restoreToken, setLoginState, userSignUp } from "../actions/userActions"; import * as SecureStore from 'expo-secure-store'; import { User } from "../../Model/User"; import { UserFactory } from "../../Model/factory/UserFactory"; @@ -38,7 +38,7 @@ export const registerUser = ( resgisterCredential : CredentialsRegister) => { "https://flad-api-production.up.railway.app/api/users", {headers} ) - dispatch(setLoginState( UserFactory.JsonToModel(user.data) )); // our action is called here + dispatch(userSignUp( UserFactory.JsonToModel(user.data) )); // our action is called here // console.log(user.data); // dispatch(setLoginState(user.data) ); // our action is called here } else { @@ -109,9 +109,6 @@ export const getRefreshToken = () => { return async dispatch => { try { let userToken : string | null = await SecureStore.getItemAsync(key); - console.log("==========key =================="); - console.log(userToken); - console.log("==========key =================="); if (userToken) { console.log("==========key2 =================="); diff --git a/src/FLAD/screens/MusicDetail.tsx b/src/FLAD/screens/MusicDetail.tsx index 6bd9abd..b176ffb 100644 --- a/src/FLAD/screens/MusicDetail.tsx +++ b/src/FLAD/screens/MusicDetail.tsx @@ -1,5 +1,5 @@ -import { NavigationProp, RouteProp } from "@react-navigation/native"; -import { View,Text,Image,StyleSheet, Dimensions, useWindowDimensions, Button, TouchableOpacity } from "react-native"; +import { NavigationProp, RouteProp, useNavigation } from "@react-navigation/native"; +import { View,Text,Image,StyleSheet, Dimensions, useWindowDimensions, Button, TouchableOpacity, ScrollView, Pressable } from "react-native"; import Animated, { interpolate, SensorType, useAnimatedSensor, useAnimatedStyle, useDerivedValue, useSharedValue, Value, withSpring, withTiming } from "react-native-reanimated"; import { BlurView } from 'expo-blur'; import qs from "qs"; @@ -14,6 +14,15 @@ import Music from "../Model/Music"; import SpotifyService from "../services/spotify/spotify.service"; import { SharedElement } from "react-navigation-shared-element"; import { SafeAreaView } from "react-native-safe-area-context"; +import { LinearGradient } from "expo-linear-gradient"; +import Icons from "../assets/icons/icons/icon"; +import FontAwesome from 'react-native-vector-icons/FontAwesome'; +import { Feather as Icon } from "@expo/vector-icons"; +import { HorizontalFlatList } from "../components/HorizontalFlatList"; +import { LittleCard } from "../components/littleCard"; +import normalize from "../components/Normalize"; +import { Circle } from "react-native-svg"; +import { AntDesign } from '@expo/vector-icons'; const halfPi = Math.PI/2; @@ -22,7 +31,7 @@ const MusicDetail = ({ route }) => { const music : Music = route.params.music; const [currentspot, setCurrentspot] = useState(music); const [sound, setSound] = useState(null); - + const [simularMusic, setSimularMusic] = useState([] as Music []); const [isPlaying, setIsPlaying] = useState(false); const loader = useSharedValue(0); useEffect(() => { @@ -218,11 +227,55 @@ const MusicDetail = ({ route }) => { await service.playMusic(id); }catch(error){} } - + + const tmpMusic2: Music[] = [ + // new Music("La pharmacie", "Jul",require("../assets/images/jul.png")), + // new Music("Deux frères", "PNL", require("../assets/images/pnl.png")), + new Music("6npyDB4mn8MO1A1h666FTk","Bambina", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png","https://p.scdn.co/mp3-preview/d38052978a79adced2187cd8b6497bb10bedc452?cid=774b29d4f13844c495f206cafdad9c86"), + // new Music("0qwxx9ouUc5kGmMWHglDpq","Stratos", "Kekra", "https://images.genius.com/ddc9cadedd1d4cef0860aaa85af9cd46.705x705x1.png",""), + new Music("03o8WSqd2K5rkGvn9IsLy2","Autobahn", "Sch", "https://images.genius.com/83b6c98680d38bde1571f6b4093244b5.1000x1000x1.jpg","https://p.scdn.co/mp3-preview/c55f95de81b8c3d0df04148da1b03bd38db56e8f?cid=774b29d4f13844c495f206cafdad9c86"), + new Music("6DPrYPPGYK218iVIZDix3i","Freeze Raël", "Freeze Corleone", "https://intrld.com/wp-content/uploads/2020/08/freeze-corleone-la-menace-fanto%CC%82me.png","https://p.scdn.co/mp3-preview/a9f9cb19ac1fe6db0d06b67decf8edbb25895a33?cid=774b29d4f13844c495f206cafdad9c86"), + // new Music("Blanka", "PNL", require("../assets/images/pnl.png")), + new Music("5GFHFEASZeJF0gyWuDDjGE","Kratos", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png","https://p.scdn.co/mp3-preview/9e854f4905c1228482e390169eb76d8520076b8f?cid=774b29d4f13844c495f206cafdad9c86"), + ] ; + const getSimilarTrack = async () => { + const service =new SpotifyService("BQC0Ne1eU2bR28A65uO-M9QPLCmGveUG5E7tQ5dD8nmzQvcz2OqUWNMYEM7zx0sEIvOPoV3S9XKSlFbFx5C3si97YAXU-4AzRiqoshfmLTFlGoPMkmGhYip9MDzshhbZM76eEWJ6x43YoXiM-TQBhI0HKh78W6a3A34TXIrn0QzU3rvZM2-ftnTfKD2e2bAN3FgDc38C"); + var simularMusic = await service.getSimilarTrack(currentspot.id,5,'FR'); + setSimularMusic(simularMusic); + } + useEffect(() => { + getSimilarTrack(); + }, []); + const navigator = useNavigation(); + return ( - - + + + + + {/* */} + + + + + + + + + + {/* */} @@ -233,51 +286,63 @@ const MusicDetail = ({ route }) => { style={[ { - width: 370, - height: 370, + // width: 370, + // width: 400, + width: 392, + height: 392, borderRadius : 24, resizeMode: 'stretch', },styleAniamatedImage ]} /> -