pre-push
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
7bef39baf9
commit
0369630fc0
After Width: | Height: | Size: 1.9 MiB |
@ -0,0 +1,6 @@
|
||||
const Lotties = {
|
||||
likeAnimation: require('./spotify-like-interaction.json')
|
||||
// riveLike : require('./light_like.riv'),
|
||||
}
|
||||
|
||||
export default Lotties;
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,53 @@
|
||||
import { SharedElement } from "react-navigation-shared-element";
|
||||
import { NavigationProp, RouteProp } from "@react-navigation/native";
|
||||
import { View,Image,StyleSheet, Dimensions, useWindowDimensions } from "react-native";
|
||||
import Animated, { interpolate, SensorType, useAnimatedSensor, useAnimatedStyle, withTiming } from "react-native-reanimated";
|
||||
|
||||
interface SpotProps {
|
||||
spot: { name: string, sourceUrl: string, index : number };
|
||||
}
|
||||
const halfPi = Math.PI/2;
|
||||
|
||||
const AnimatedParalax = ({}) => {
|
||||
const {width, height} = useWindowDimensions();
|
||||
const sensor = useAnimatedSensor(SensorType.ROTATION);
|
||||
const styleAniamatedImage = useAnimatedStyle(() => {
|
||||
const {yaw, pitch, roll} = sensor.sensor.value;
|
||||
const verticalAxis =interpolate(
|
||||
pitch,
|
||||
[-halfPi,halfPi],
|
||||
[-25, 25]
|
||||
)
|
||||
const horizontalAxis =interpolate(
|
||||
roll,
|
||||
[-halfPi*2,halfPi*2],
|
||||
[-35, 35]
|
||||
)
|
||||
return {
|
||||
top : verticalAxis,
|
||||
left : horizontalAxis,
|
||||
};
|
||||
|
||||
})
|
||||
return (
|
||||
<View style={{ flex: 1, justifyContent : 'flex-start', alignItems : 'center' }}>
|
||||
<Animated.Image
|
||||
source={{
|
||||
uri:spot.sourceUrl ,
|
||||
}}
|
||||
style={[
|
||||
{
|
||||
width: 370,
|
||||
height: 370,
|
||||
borderRadius : 24,
|
||||
resizeMode: 'stretch',
|
||||
},styleAniamatedImage
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default AnimatedParalax;
|
@ -0,0 +1,82 @@
|
||||
import { View, StyleSheet, Dimensions, Image, Pressable, TouchableWithoutFeedback, TouchableOpacity, TouchableHighlight } from "react-native";
|
||||
import Animated, {
|
||||
Layout,
|
||||
Transition,
|
||||
ZoomIn,
|
||||
ZoomOut,
|
||||
} from "react-native-reanimated";
|
||||
|
||||
const { width } = Dimensions.get("window");
|
||||
const SIZE = width / 3;
|
||||
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";
|
||||
|
||||
|
||||
interface ArtistProps {
|
||||
artist: Music;
|
||||
onPress: () => void;
|
||||
}
|
||||
export const Artist = ({ artist, onPress }: ArtistProps) => {
|
||||
const source = typeof artist.image === 'string' ? { uri: artist.image } : artist.image;
|
||||
//@ts-ignore
|
||||
const onSingleTapEvent = (event) => {
|
||||
if (event.nativeEvent.state === State.ACTIVE) {
|
||||
alert('Hey single tap!');
|
||||
}
|
||||
};
|
||||
const doubleTapRef = useRef(null);
|
||||
const [selected,setSeleted] = useState(false);
|
||||
const onS = () => {
|
||||
setSeleted(!selected);
|
||||
onPress();
|
||||
};
|
||||
return (
|
||||
<TouchableOpacity onPress={onS}>
|
||||
<Animated.View
|
||||
style={styles.container}
|
||||
entering={ZoomIn}
|
||||
exiting={ZoomOut}
|
||||
layout={Layout.delay(200)}
|
||||
>
|
||||
<View style={styles.card}>
|
||||
<Image source={source} style={styles.image} />
|
||||
{ selected && (
|
||||
<View style={styles.cheked}>
|
||||
<Icon name="check-circle" color="black" size={24} />
|
||||
</View>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
</View>
|
||||
</Animated.View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
width: SIZE,
|
||||
height: SIZE,
|
||||
padding: 8,
|
||||
},
|
||||
card: {
|
||||
flex: 1,
|
||||
padding: 8,
|
||||
alignItems: "flex-end",
|
||||
},
|
||||
image: {
|
||||
borderRadius: 8,
|
||||
...StyleSheet.absoluteFillObject,
|
||||
width: undefined,
|
||||
height: undefined,
|
||||
},
|
||||
cheked : {
|
||||
backgroundColor : "white",
|
||||
borderRadius : 100,
|
||||
alignItems : "center",
|
||||
|
||||
|
||||
}
|
||||
});
|
@ -0,0 +1,114 @@
|
||||
import { View, Text, Image , Dimensions, StyleSheet } from 'react-native'
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import Animated,{ Extrapolate, interpolate, runOnJS, useAnimatedGestureHandler, useAnimatedStyle, useSharedValue, withRepeat, withSpring, withTiming } from 'react-native-reanimated';
|
||||
|
||||
import { PanGestureHandler, PanGestureHandlerGestureEvent } from 'react-native-gesture-handler';
|
||||
import * as Haptics from 'expo-haptics';
|
||||
|
||||
const {width : wWidht} = Dimensions.get("window");
|
||||
const SCREEN_HEIGHT = Dimensions.get('window').height
|
||||
const SCREEN_WIDTH = Dimensions.get('window').width
|
||||
// const width = wWidht *0.75;
|
||||
// const height = wWidht * (465/264);
|
||||
// const borderRadius = 24;
|
||||
|
||||
const size= 100
|
||||
const FladLoading = () => {
|
||||
|
||||
const progresse = useSharedValue(1);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
// withTiming, withSpring
|
||||
progresse.value =withRepeat( withTiming(0.01,{duration : 750}), -1,true);
|
||||
}, [progresse]);
|
||||
|
||||
const breatheStyle = useAnimatedStyle(() => {
|
||||
const borderRange = interpolate
|
||||
( progresse.value,
|
||||
[0, 1],
|
||||
[(0*size) / 2,(1*size)/2],
|
||||
);
|
||||
return {
|
||||
justifyContent : 'center',
|
||||
alignItems : 'center',
|
||||
width : size,
|
||||
height : size,
|
||||
shadowColor : "#DA1D1D",
|
||||
shadowOffset : {width : 0, height : 0},
|
||||
shadowOpacity : 1,
|
||||
shadowRadius :borderRange,
|
||||
};
|
||||
});
|
||||
const breatheStyle2 = useAnimatedStyle(() => {
|
||||
const borderRange = interpolate
|
||||
( progresse.value,
|
||||
[0, 1],
|
||||
[(0*size) / 2,(1*size)/2],
|
||||
);
|
||||
return {
|
||||
|
||||
borderRadius : borderRange,
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
const breatheStyleSquare = useAnimatedStyle(() => {
|
||||
const borderRange = interpolate
|
||||
( progresse.value,
|
||||
[0, 1],
|
||||
[(size+20),(size)],
|
||||
);
|
||||
return {
|
||||
|
||||
width : borderRange,
|
||||
height : borderRange,
|
||||
borderRadius : borderRange/2,
|
||||
borderWidth : size/10,
|
||||
borderColor : "#F80404",
|
||||
shadowColor : "#F40C1C",
|
||||
shadowOffset : {width : 0, height : 0},
|
||||
shadowOpacity : 1,
|
||||
shadowRadius :10,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<View style={{flex : 1, justifyContent : 'center', alignItems :'center'}}>
|
||||
|
||||
<Animated.View style={[{backgroundColor : '#B40404', justifyContent : 'center', alignItems : 'center'}, breatheStyleSquare]}>
|
||||
<Animated.Image source={require('../assets/icons/icon.png')} style={[{height: size, width : size, borderColor : '#fff',borderRadius : size/2, borderWidth : 3}]}/>
|
||||
</Animated.View>
|
||||
{/* <Animated.View style={[ {backgroundColor : 'green'},breatheStyleSquare]}>
|
||||
</Animated.View> */}
|
||||
|
||||
{/* <Image source={require('../assets/icons/Spotify_-_Animation_1.gif')}/> */}
|
||||
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
card : {
|
||||
justifyContent : 'center',
|
||||
alignItems : 'center',
|
||||
},
|
||||
image : {
|
||||
borderRadius : 24,
|
||||
resizeMode: 'stretch',
|
||||
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
width: '100%',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}
|
||||
})
|
||||
|
||||
export default FladLoading;
|
||||
|
@ -0,0 +1,83 @@
|
||||
import { useState } from "react";
|
||||
import { FlatList, ScrollView } from "react-native";
|
||||
import Music from "../Model/Music";
|
||||
import { Artist } from "./Artist";
|
||||
import { StyleSheet } from "react-native";
|
||||
|
||||
export const ArtistLayout = () => {
|
||||
const MUSIC_LIST : Music[] = [
|
||||
new Music("La pharmacie", "Jul",require("../assets/images/jul.png")),
|
||||
new Music("Deux frères", "PNL", require("../assets/images/pnl.png")),
|
||||
new Music("Bambina", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png"),
|
||||
new Music("Stratos", "Kekra", "https://images.genius.com/ddc9cadedd1d4cef0860aaa85af9cd46.705x705x1.png"),
|
||||
new Music("Autobahn", "Sch", "https://images.genius.com/83b6c98680d38bde1571f6b4093244b5.1000x1000x1.jpg"),
|
||||
new Music("Freeze Raël", "Freeze Corleone", "https://intrld.com/wp-content/uploads/2020/08/freeze-corleone-la-menace-fanto%CC%82me.png"),
|
||||
new Music("Blanka", "PNL", require("../assets/images/pnl.png")),
|
||||
new Music("Kratos", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png"),
|
||||
]
|
||||
const [artists, setArtists] = useState<Music[]>(MUSIC_LIST);
|
||||
const [selectedArtists, setSelectedArtists] = useState<typeof MUSIC_LIST> ([]);
|
||||
|
||||
return (
|
||||
<ScrollView contentContainerStyle={styles.container}>
|
||||
{artists.map((artist, i) => (
|
||||
<Artist
|
||||
artist={artist}
|
||||
key={artist.title}
|
||||
onPress={() => {
|
||||
// artists.splice(i, 1);
|
||||
// // 2 implementation
|
||||
const tmppArtist = new Music("Kratos", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png");
|
||||
|
||||
// const existingObjIndex = selectedArtists.findIndex(obj => obj.title === tmppArtist.title);
|
||||
// if (existingObjIndex === -1) {
|
||||
// selectedArtists.push(tmppArtist);
|
||||
// } else {
|
||||
// selectedArtists.splice(existingObjIndex, 1);
|
||||
// }
|
||||
// setSelectedArtists([...selectedArtists]);
|
||||
// 1 implementation
|
||||
// setSelectedArtists(selectedArtists.findIndex(obj => obj.title === tmppArtist.title) === -1
|
||||
// ? [...selectedArtists, tmppArtist]
|
||||
// : selectedArtists.filter(obj => obj.title !== tmppArtist.title))
|
||||
// 3 implementations
|
||||
// use the selectedProps of the Artist Component
|
||||
// then when we need to finish
|
||||
// onPress{ () => setSelectedArtists([...selectedArtists,artists.filter(artist => artist.selected)])}
|
||||
|
||||
artists.push(tmppArtist);
|
||||
setArtists([...artists]);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
{/* <FlatList
|
||||
data={artists}
|
||||
// need to reverse colums oreder
|
||||
numColumns = {3}
|
||||
renderItem={({ item }) => (
|
||||
<Artist
|
||||
artist={item}
|
||||
key={item.title}
|
||||
onPress={() => {
|
||||
artists.push(new Music("Kratos", "PNL", "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png"));
|
||||
setArtists([...artists]);
|
||||
}}/>
|
||||
)}
|
||||
keyExtractor={(item: Music) => item.title }
|
||||
// ListEmptyComponent = {}
|
||||
/> */}
|
||||
|
||||
</ScrollView>
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap",
|
||||
|
||||
},
|
||||
});
|
@ -1,12 +1,37 @@
|
||||
export const cards = [{
|
||||
name : "blue",
|
||||
sourceUrl : "https://i.ebayimg.com/images/g/rY0AAOSw97djEo2C/s-l500.jpg",
|
||||
index : 3
|
||||
sourceUrl : "https://th.bing.com/th/id/R.dbf87f0d8cbfd078ab6a589a5d921994?rik=1%2f6KliMpOAeh8A&pid=ImgRaw&r=0",
|
||||
index : 4
|
||||
},
|
||||
{
|
||||
name : "her",
|
||||
sourceUrl : "https://i.ebayimg.com/images/g/rY0AAOSw97djEo2C/s-l500.jpg",
|
||||
index : 9
|
||||
},
|
||||
{
|
||||
name : "gambino",
|
||||
sourceUrl : "https://th.bing.com/th/id/R.0b2d1a59bfda9b1a49ecb561e08535a8?rik=Xyc35OZU%2f6VOVw&pid=ImgRaw&r=0",
|
||||
index : 3
|
||||
}
|
||||
},
|
||||
{
|
||||
name : "PNL",
|
||||
sourceUrl : "https://upload.wikimedia.org/wikipedia/en/a/a0/PNL_-_Dans_la_l%C3%A9gende.png",
|
||||
index : 10
|
||||
},
|
||||
{
|
||||
name : "Freeze Raël",
|
||||
sourceUrl : "https://intrld.com/wp-content/uploads/2020/08/freeze-corleone-la-menace-fanto%CC%82me.png",
|
||||
index : 23
|
||||
},
|
||||
{
|
||||
name : "Sch",
|
||||
sourceUrl : "https://images.genius.com/83b6c98680d38bde1571f6b4093244b5.1000x1000x1.jpg",
|
||||
index : 44
|
||||
},
|
||||
{
|
||||
name : "Stratos",
|
||||
sourceUrl : "https://images.genius.com/ddc9cadedd1d4cef0860aaa85af9cd46.705x705x1.png",
|
||||
index : 89
|
||||
},
|
||||
|
||||
]
|
||||
]
|
||||
|
@ -0,0 +1 @@
|
||||
export const API_URL = "https://flad-api-production.up.railway.app"
|
@ -0,0 +1,67 @@
|
||||
import Navigation from './Navigation';
|
||||
import { StyleSheet,SafeAreaView } from 'react-native';
|
||||
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||
import StartNavigation from './StartNavigation';
|
||||
import { Provider, useDispatch, useSelector } from 'react-redux';
|
||||
import store from '../redux/store';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import * as SplashScreen from 'expo-splash-screen';
|
||||
import { View } from 'react-native';
|
||||
import { getRefreshToken } from '../redux/thunk/authThunk';
|
||||
|
||||
SplashScreen.preventAutoHideAsync();
|
||||
|
||||
export default function AuthNavigation() {
|
||||
//@ts-ignore
|
||||
const appIsReady : boolean = useSelector(state => state.userReducer.loading);
|
||||
//@ts-ignore
|
||||
const isLogin : boolean = useSelector(state => state.userReducer.isLogedIn);
|
||||
// const userToken : string = useSelector(state => state.userReducer.userFladToken);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
async function prepare() {
|
||||
console.log(appIsReady, "1 AuthNav")
|
||||
|
||||
//@ts-ignore
|
||||
await dispatch(getRefreshToken())
|
||||
await SplashScreen.hideAsync();
|
||||
}
|
||||
prepare();
|
||||
}, [dispatch]);
|
||||
|
||||
const onStackRootView = useCallback(async () => {
|
||||
if (appIsReady) {
|
||||
await SplashScreen.hideAsync();
|
||||
}
|
||||
}, [appIsReady]);
|
||||
|
||||
if (appIsReady == false) {
|
||||
console.log(appIsReady, "T9 AuthNav")
|
||||
return null;
|
||||
}
|
||||
console.log(appIsReady, "k9 AuthNav")
|
||||
// console.log(userToken, "k9 AuthNav")
|
||||
return (
|
||||
<>
|
||||
{isLogin ? (
|
||||
/* {userToken != null ? ( */
|
||||
<SafeAreaView style={styles.mainSafeArea} >
|
||||
<Navigation/>
|
||||
</SafeAreaView>
|
||||
|
||||
) :
|
||||
<SafeAreaProvider >
|
||||
<StartNavigation/>
|
||||
</SafeAreaProvider>
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
const styles = StyleSheet.create({
|
||||
mainSafeArea: {
|
||||
flex: 1,
|
||||
backgroundColor: "#141414",
|
||||
}
|
||||
});
|
@ -0,0 +1,38 @@
|
||||
import React, {Component} from 'react';
|
||||
import FavoritePage from '../screens/favoritePage';
|
||||
import { createStackNavigator } from '@react-navigation/stack';
|
||||
import Spot from '../screens/spot'
|
||||
import { createSharedElementStackNavigator } from "react-navigation-shared-element";
|
||||
import SpotDetailsPage from '../screens/SpotDetailsPage';
|
||||
|
||||
|
||||
export default function SpotNavigation() {
|
||||
// const Stack = createSharedElementStackNavigator();
|
||||
const Stack = createStackNavigator();
|
||||
|
||||
return (
|
||||
<Stack.Navigator screenOptions={{
|
||||
gestureEnabled: false,
|
||||
headerShown: false,
|
||||
cardOverlayEnabled: true,
|
||||
|
||||
}}
|
||||
>
|
||||
<Stack.Screen
|
||||
name="Spots"
|
||||
component={Spot}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="DetailsSpot"
|
||||
component={SpotDetailsPage}
|
||||
/>
|
||||
{/* <Stack.Screen
|
||||
name="DetailsSpot"
|
||||
component={SpotDetailsPage}
|
||||
sharedElements={(route) => {
|
||||
return [route.params.spot.name]
|
||||
}}
|
||||
/> */}
|
||||
</Stack.Navigator>
|
||||
)
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
// export const UserLogin = (username: string, password: string) => {
|
||||
// return {
|
||||
// type: userTypes.LOGIN,
|
||||
// playload : username, password
|
||||
// };
|
||||
// }
|
@ -0,0 +1,8 @@
|
||||
import {spotTypes} from "../types/spotTypes";
|
||||
|
||||
export const setSpotList = (spotList: Spot[]) => {
|
||||
return {
|
||||
type: spotTypes.FETCH_SPOT,
|
||||
payload: spotList,
|
||||
};
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
import { userTypes } from "../types/userTypes";
|
||||
|
||||
|
||||
export interface Credentials {
|
||||
email : string,
|
||||
password : string
|
||||
}
|
||||
// export const setLoggedInState = loggedInState => (
|
||||
// {
|
||||
// type: types.SET_LOGGED_IN_STATE,
|
||||
// loggedInState,
|
||||
// }
|
||||
// );
|
||||
export const setLoginState = (cred : Credentials) => {
|
||||
return {
|
||||
type: userTypes.LOGIN,
|
||||
playload : cred
|
||||
};
|
||||
}
|
||||
|
||||
export const restoreToken = (token : string) => {
|
||||
return {
|
||||
type: userTypes.RESTORE_TOKEN,
|
||||
playload : token
|
||||
};
|
||||
}
|
||||
// export const UserLogin = (username: string, password: string) => {
|
||||
// return {
|
||||
// type: userTypes.LOGIN,
|
||||
// playload : username, password
|
||||
// };
|
||||
// }
|
||||
|
||||
export const UserLogout = () => {
|
||||
return {
|
||||
type: userTypes.USER_LOGOUT,
|
||||
};
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
const initialState = {
|
||||
spot: [],
|
||||
favoriteMusic: [],
|
||||
}
|
||||
|
||||
const appReducer = (state = initialState, action : any) => {
|
||||
switch (action.type) {
|
||||
case ADD_FAVORITE_MUSICS:
|
||||
return {...state, favoriteMusic: state.favoriteMusic.push(action.payload)};
|
||||
case REMOVE_FAVORITE_MUSICS:
|
||||
return {...state, favoriteMusic: state.favoriteMusic};
|
||||
case FETCH_SPOT:
|
||||
return {...state, spot: action.payload};
|
||||
case FETCH_DISCOVERIES:
|
||||
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default appReducer
|
@ -0,0 +1,18 @@
|
||||
|
||||
Uri getApiUrlAuthorize() => _api.identification.urlAuthorize;
|
||||
|
||||
String getApiRedirectUrl() => _api.identification.redirectUri;
|
||||
|
||||
String getIdSpotify() => _currentUser.idSpotify;
|
||||
|
||||
String getIdDafl() => _currentUser.idDafl;
|
||||
|
||||
|
||||
case getCompleteMusic
|
||||
|
||||
playTrack(String id)
|
||||
|
||||
case addToPlaylist:
|
||||
return {...state, spot: action.payload}
|
||||
|
||||
case removeFromPlaylist:
|
@ -0,0 +1,52 @@
|
||||
import { userTypes } from "../types/userTypes";
|
||||
const initialState = {
|
||||
loading: false,
|
||||
user: {}, // for user object
|
||||
userFladToken: null, // for storing the JWT
|
||||
userSpotifyToken : null,
|
||||
error: null,
|
||||
isLogedIn: false,
|
||||
}
|
||||
|
||||
const userReducer = (state = initialState, action : any) => {
|
||||
switch (action.type) {
|
||||
// just for the navigation and speciafly use
|
||||
// and
|
||||
case userTypes.RESTORE_TOKEN:
|
||||
console.log(state.loading, "((((((((((((((((((((((((((((((((((((userRducer))))))))))))))))))))))))))))))))))))");
|
||||
|
||||
console.log(state.userFladToken, "userRducer");
|
||||
console.log(state.loading, "((((((((((((((((((((((((((((((((((((userRducer))))))))))))))))))))))))))))))))))))");
|
||||
|
||||
return {
|
||||
...state,
|
||||
userFladToken : action.playload,
|
||||
loading: true,
|
||||
// isLogedIn: true,
|
||||
};
|
||||
|
||||
case userTypes.LOGIN:
|
||||
return {
|
||||
...state,
|
||||
user :action.payload,
|
||||
isLogedIn: true
|
||||
};
|
||||
case userTypes.SIGNUP:
|
||||
return {
|
||||
...state,
|
||||
user :action.payload,
|
||||
isLogedIn: true
|
||||
};
|
||||
// case USER_SIGNUP:
|
||||
// return {...state, nounours: action.payload};
|
||||
case userTypes.USER_LOGOUT:
|
||||
return {...state,
|
||||
user :null,
|
||||
isLogedIn: false }
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
export default userReducer
|
||||
|
||||
|
@ -0,0 +1,15 @@
|
||||
import {configureStore} from '@reduxjs/toolkit'
|
||||
import appReducer from './reducers/appReducer';
|
||||
import userReducer from './reducers/userReducer';
|
||||
|
||||
// Reference here all your application reducers
|
||||
const reducer = {
|
||||
// appReducer: appReducer,
|
||||
userReducer: userReducer
|
||||
}
|
||||
|
||||
const store = configureStore({
|
||||
reducer : reducer,
|
||||
},);
|
||||
|
||||
export default store;
|
@ -0,0 +1,127 @@
|
||||
//Define your action creators that will be responsible for asynchronous operations
|
||||
|
||||
import axios from "axios";
|
||||
import { json } from "express";
|
||||
import { useEffect } from "react";
|
||||
import { API_URL } from "../../fladConfig";
|
||||
import { Credentials, restoreToken, setLoginState } from "../actions/userActions";
|
||||
import * as SecureStore from 'expo-secure-store';
|
||||
|
||||
const key = 'userToken';
|
||||
|
||||
export const registerUser = ( resgisterCredential : any) => {
|
||||
//@ts-ignore
|
||||
return async dispatch => {
|
||||
try {
|
||||
const config = {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
const resp = await axios.post(
|
||||
`${API_URL}/api/users/register`,
|
||||
resgisterCredential,
|
||||
config
|
||||
)
|
||||
if (resp.data.msg === 'success') { // response success checking logic could differ
|
||||
await SecureStore.setItemAsync(key, resp.data.token);
|
||||
dispatch(setLoginState(resp.data.user) ); // our action is called here
|
||||
} else {
|
||||
console.log('Login Failed', 'Username or Password is incorrect');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log('Error---------', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
export const userLogin = ( loginCredential : Credentials) => {
|
||||
//@ts-ignore
|
||||
return async dispatch => {
|
||||
try {
|
||||
console.log(loginCredential);
|
||||
|
||||
const config = {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
// const resppp = await axios.get(`${API_URL}/toto`);
|
||||
// console.log(resppp.data, "sddsd");
|
||||
|
||||
const resp = await axios.post(
|
||||
"https://flad-api-production.up.railway.app/api/users/login",
|
||||
loginCredential,
|
||||
config
|
||||
)
|
||||
console.log("====================================================================================")
|
||||
console.log(resp.data)
|
||||
console.log("====================================================================================")
|
||||
if (resp.data.token) {
|
||||
console.log(resp.data.token);
|
||||
const token = resp.data.token;
|
||||
await SecureStore.setItemAsync(key, token);
|
||||
const headers = {
|
||||
'Authorization': 'Bearer ' + token};
|
||||
|
||||
const user = await axios.get(
|
||||
"https://flad-api-production.up.railway.app/api/users",
|
||||
{headers}
|
||||
)
|
||||
// dispatch(setLoginState(resp.data.user) ); // our action is called here
|
||||
|
||||
dispatch(setLoginState(user.data) ); // our action is called here
|
||||
} else {
|
||||
console.log('Login Failed', 'Username or Password is incorrect');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log('Error---------', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const getRefreshToken = () => {
|
||||
//@ts-ignore
|
||||
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 ==================");
|
||||
console.log(userToken);
|
||||
console.log("==========key ==================");
|
||||
|
||||
dispatch(restoreToken(userToken) );
|
||||
|
||||
} else {
|
||||
console.log("==========OOOOOORRRRRRRRHHHHHHHHHH ==================");
|
||||
const empty = "";
|
||||
dispatch(restoreToken(empty) );
|
||||
|
||||
console.log("merddee");
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('Error---------', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// const logIn = (email, password) => {
|
||||
// const action = (dispatch) => {
|
||||
// if (email === user.email && password === user.password) {
|
||||
// dispatch(setLoggedInState(true));
|
||||
// return true;
|
||||
// }
|
||||
// dispatch(setLoggedInState(false));
|
||||
// return false;
|
||||
// };
|
||||
// return action;
|
||||
// };
|
||||
// better
|
||||
async function save(key : string, value : string) {
|
||||
await SecureStore.setItemAsync(key, value);
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
//Define your action creators that will be responsible for asynchronous operations
|
||||
|
||||
import { API_URL } from "../../fladConfig";
|
||||
|
||||
|
||||
export type CreateSpotReqBody = {
|
||||
id : string;
|
||||
name : string;
|
||||
artist : string;
|
||||
linkCover : string;
|
||||
user : string;
|
||||
}
|
||||
|
||||
// export const getSpotList = () => {
|
||||
// return async dispatch => {
|
||||
// try {
|
||||
|
||||
// const spotPromise = await fetch(`${API_URL}/spotify/spot`);
|
||||
// const spotJson = await spotPromise.json();
|
||||
// const spotList: Spot[] = spotJson.map(spot => {
|
||||
|
||||
// } );
|
||||
|
||||
// dispatch(setNounoursList(spotList));
|
||||
// } catch (error) {
|
||||
// console.log('Error---------', error);
|
||||
// }
|
||||
// }
|
||||
// }
|
@ -0,0 +1,3 @@
|
||||
export const spotTypes = {
|
||||
FETCH_SPOT : 'FETCH_NOUNOURS',
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
|
||||
export const userTypes = {
|
||||
LOGIN: 'LOGIN',
|
||||
SIGNUP: 'SIGNUP',
|
||||
UPDATE_USER: 'UPDATE_USER',
|
||||
UPDATE_PROFILE_PICTURE: 'UPDATE_PROFILE_PICTURE',
|
||||
USER_LOGOUT : 'USER_LOGOUT',
|
||||
RESTORE_TOKEN : "RESTORE_TOKEN"
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
import { SharedElement } from "react-navigation-shared-element";
|
||||
import { NavigationProp, RouteProp } from "@react-navigation/native";
|
||||
import { View,Text,Image,StyleSheet, Dimensions, useWindowDimensions } from "react-native";
|
||||
import Animated, { interpolate, SensorType, useAnimatedSensor, useAnimatedStyle, withSpring, withTiming } from "react-native-reanimated";
|
||||
import { BlurView } from 'expo-blur';
|
||||
|
||||
interface SpotProps {
|
||||
spot: { name: string, sourceUrl: string, index : number };
|
||||
}
|
||||
const halfPi = Math.PI/2;
|
||||
|
||||
// const {width : wWidht} = Dimensions.get("window");
|
||||
//@ts-ignore
|
||||
const SpotDetailsPage = ({ route }) => {
|
||||
const {width, height} = useWindowDimensions();
|
||||
console.log("====================================");
|
||||
console.log(route);
|
||||
|
||||
const spot : { name: string, sourceUrl: string, index : number } = route.params.spot;
|
||||
console.log(spot);
|
||||
const sensor = useAnimatedSensor(SensorType.ROTATION);
|
||||
const styleAniamatedImage = useAnimatedStyle(() => {
|
||||
const {yaw, pitch, roll} = sensor.sensor.value;
|
||||
const verticalAxis =interpolate(
|
||||
pitch,
|
||||
[-halfPi,halfPi],
|
||||
[-30, 30]
|
||||
)
|
||||
const horizontalAxis =interpolate(
|
||||
roll,
|
||||
[-halfPi*2,halfPi*2],
|
||||
[-30, 30]
|
||||
)
|
||||
return {
|
||||
top : withSpring( verticalAxis),
|
||||
left : withSpring(horizontalAxis),
|
||||
};
|
||||
|
||||
})
|
||||
return (
|
||||
<View style={{ flex: 1, justifyContent : 'flex-start', alignItems : 'center' }}>
|
||||
{/* <SharedElement id={spot.name} style={{ flex: 1 }}> */}
|
||||
<Animated.Image
|
||||
source={{
|
||||
uri:spot.sourceUrl ,
|
||||
}}
|
||||
style={[
|
||||
{
|
||||
|
||||
width: 370,
|
||||
height: 370,
|
||||
borderRadius : 24,
|
||||
resizeMode: 'stretch',
|
||||
},styleAniamatedImage
|
||||
]}
|
||||
/>
|
||||
|
||||
{/* <View style={detailRadicalStyle.container}>
|
||||
<Text style={detailRadicalStyle.radicalText}>{props.character}</Text>
|
||||
<SvgXml
|
||||
xml={props.icon
|
||||
.replace(/fill="#[0-9a-f]{6}"/g, `fill=${detailRadicalStyle.svg.color}`)}
|
||||
width="30"
|
||||
height="30"
|
||||
opacity={0.5}
|
||||
style={detailRadicalStyle.radicalIcon}
|
||||
|
||||
/>
|
||||
</View> */}
|
||||
{/* </SharedElement> */}
|
||||
</View>
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
export default SpotDetailsPage;
|
Loading…
Reference in new issue