| @@ -8,6 +8,7 @@ npm-debug.* | |||
| *.mobileprovision | |||
| *.orig.* | |||
| web-build/ | |||
| ios/ | |||
| # macOS | |||
| .DS_Store | |||
| @@ -1,63 +1,38 @@ | |||
| import 'react-native-gesture-handler'; | |||
| import React from 'react'; | |||
| import { StyleSheet, Text, View } from 'react-native'; | |||
| import { NavigationContainer } from '@react-navigation/native'; | |||
| import { createBottomTabNavigator } from "@react-navigation/bottom-tabs"; | |||
| import { Provider } from 'react-redux'; | |||
| import { SafeAreaProvider } from 'react-native-safe-area-context'; | |||
| import "react-native-gesture-handler"; | |||
| import React, { useContext } from "react"; | |||
| import { NavigationContainer } from "@react-navigation/native"; | |||
| import { Provider } from "react-redux"; | |||
| import store from "./store"; | |||
| // import { Counter } from './screens/Counter' | |||
| import { LogIn } from './screens/LogIn'; | |||
| import { Counter } from './screens/Counter'; | |||
| import { createNativeStackNavigator } from '@react-navigation/native-stack'; | |||
| const A = () => <View><Text>Home</Text></View> | |||
| const B = () => <View><Text>Settings</Text></View> | |||
| const C = () => <View><Text>C</Text></View> | |||
| const Tab = createBottomTabNavigator(); | |||
| const Stack = createNativeStackNavigator(); | |||
| const Home = () => { | |||
| return ( | |||
| <Tab.Navigator> | |||
| <Tab.Screen name="A" component={A} /> | |||
| <Tab.Screen name="B" component={B} /> | |||
| </Tab.Navigator> | |||
| ) | |||
| } | |||
| import { useFonts } from "expo-font"; | |||
| import { AuthProvider } from "./context/AuthContext"; | |||
| import RootNavigation from "./navigation/RootNavigation"; | |||
| function App() { | |||
| return ( | |||
| <NavigationContainer> | |||
| <Stack.Navigator> | |||
| {/* <Stack.Screen name='Counter' component={Counter} /> */} | |||
| <Stack.Screen name="Login" component={LogIn} /> | |||
| <Stack.Screen name="Home" component={Home} /> | |||
| <Stack.Screen name="Profile" component={C} /> | |||
| </Stack.Navigator> | |||
| <RootNavigation /> | |||
| </NavigationContainer> | |||
| ); | |||
| } | |||
| const AppWrapper = () => { | |||
| const [fontsLoaded] = useFonts({ | |||
| "poppins-regular": require("./assets/fonts/Poppins-Regular.ttf"), | |||
| "poppins-semibold": require("./assets/fonts/Poppins-SemiBold.ttf"), | |||
| }); | |||
| if (!fontsLoaded) { | |||
| return null; | |||
| } | |||
| return ( | |||
| <Provider store={store}> | |||
| <SafeAreaProvider> | |||
| <AuthProvider> | |||
| <Provider store={store}> | |||
| <App /> | |||
| </SafeAreaProvider> | |||
| </Provider> | |||
| </Provider> | |||
| </AuthProvider> | |||
| ); | |||
| }; | |||
| const styles = StyleSheet.create({ | |||
| container: { | |||
| flex: 1, | |||
| backgroundColor: '#fff', | |||
| alignItems: 'center', | |||
| justifyContent: 'center', | |||
| }, | |||
| }); | |||
| export default AppWrapper; | |||
| export default AppWrapper; | |||
| @@ -1,15 +1,16 @@ | |||
| { | |||
| "expo": { | |||
| "name": "native", | |||
| "name": "Diligent Template", | |||
| "slug": "native", | |||
| "version": "1.0.0", | |||
| "orientation": "portrait", | |||
| "icon": "./assets/icon.png", | |||
| "icon": "./assets/images/diligent-logo.png", | |||
| "splash": { | |||
| "image": "./assets/splash.png", | |||
| "image": "./assets/images/diligent-purple.png", | |||
| "resizeMode": "contain", | |||
| "backgroundColor": "#ffffff" | |||
| }, | |||
| "scheme": "com.diligent.template", | |||
| "updates": { | |||
| "fallbackToCacheTimeout": 0 | |||
| }, | |||
| @@ -17,9 +18,11 @@ | |||
| "**/*" | |||
| ], | |||
| "ios": { | |||
| "supportsTablet": true | |||
| "supportsTablet": true, | |||
| "bundleIdentifier": "com.diligent.template" | |||
| }, | |||
| "android": { | |||
| "package": "com.diligent.template", | |||
| "adaptiveIcon": { | |||
| "foregroundImage": "./assets/adaptive-icon.png", | |||
| "backgroundColor": "#FFFFFF" | |||
| @@ -27,6 +30,11 @@ | |||
| }, | |||
| "web": { | |||
| "favicon": "./assets/favicon.png" | |||
| }, | |||
| "extra": { | |||
| "eas": { | |||
| "projectId": "cb00f072-1d4c-4c94-ac22-f34e72808a6b" | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1 @@ | |||
| <svg xmlns="http://www.w3.org/2000/svg" data-name="Ebene 1" viewBox="0 0 1024 1024"><path fill="#1877f2" d="M1024,512C1024,229.23016,794.76978,0,512,0S0,229.23016,0,512c0,255.554,187.231,467.37012,432,505.77777V660H302V512H432V399.2C432,270.87982,508.43854,200,625.38922,200,681.40765,200,740,210,740,210V336H675.43713C611.83508,336,592,375.46667,592,415.95728V512H734L711.3,660H592v357.77777C836.769,979.37012,1024,767.554,1024,512Z"/><path fill="#fff" d="M711.3,660,734,512H592V415.95728C592,375.46667,611.83508,336,675.43713,336H740V210s-58.59235-10-114.61078-10C508.43854,200,432,270.87982,432,399.2V512H302V660H432v357.77777a517.39619,517.39619,0,0,0,160,0V660Z"/></svg> | |||
| @@ -0,0 +1,9 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <svg viewBox="0 0 24 24" width="24" height="24" xmlns="http://www.w3.org/2000/svg"> | |||
| <g transform="matrix(1, 0, 0, 1, 27.009001, -39.238998)"> | |||
| <path fill="#4285F4" d="M -3.264 51.509 C -3.264 50.719 -3.334 49.969 -3.454 49.239 L -14.754 49.239 L -14.754 53.749 L -8.284 53.749 C -8.574 55.229 -9.424 56.479 -10.684 57.329 L -10.684 60.329 L -6.824 60.329 C -4.564 58.239 -3.264 55.159 -3.264 51.509 Z"/> | |||
| <path fill="#34A853" d="M -14.754 63.239 C -11.514 63.239 -8.804 62.159 -6.824 60.329 L -10.684 57.329 C -11.764 58.049 -13.134 58.489 -14.754 58.489 C -17.884 58.489 -20.534 56.379 -21.484 53.529 L -25.464 53.529 L -25.464 56.619 C -23.494 60.539 -19.444 63.239 -14.754 63.239 Z"/> | |||
| <path fill="#FBBC05" d="M -21.484 53.529 C -21.734 52.809 -21.864 52.039 -21.864 51.239 C -21.864 50.439 -21.724 49.669 -21.484 48.949 L -21.484 45.859 L -25.464 45.859 C -26.284 47.479 -26.754 49.299 -26.754 51.239 C -26.754 53.179 -26.284 54.999 -25.464 56.619 L -21.484 53.529 Z"/> | |||
| <path fill="#EA4335" d="M -14.754 43.989 C -12.984 43.989 -11.404 44.599 -10.154 45.789 L -6.734 42.369 C -8.804 40.429 -11.514 39.239 -14.754 39.239 C -19.444 39.239 -23.494 41.939 -25.464 45.859 L -21.484 48.949 C -20.534 46.099 -17.884 43.989 -14.754 43.989 Z"/> | |||
| </g> | |||
| </svg> | |||
| @@ -0,0 +1 @@ | |||
| <svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 112.197 112.197" viewBox="0 0 112.197 112.197"><circle cx="56.099" cy="56.098" r="56.098" fill="#55acee"/><path fill="#f1f2f2" d="M90.461,40.316c-2.404,1.066-4.99,1.787-7.702,2.109c2.769-1.659,4.894-4.284,5.897-7.417 c-2.591,1.537-5.462,2.652-8.515,3.253c-2.446-2.605-5.931-4.233-9.79-4.233c-7.404,0-13.409,6.005-13.409,13.409 c0,1.051,0.119,2.074,0.349,3.056c-11.144-0.559-21.025-5.897-27.639-14.012c-1.154,1.98-1.816,4.285-1.816,6.742 c0,4.651,2.369,8.757,5.965,11.161c-2.197-0.069-4.266-0.672-6.073-1.679c-0.001,0.057-0.001,0.114-0.001,0.17 c0,6.497,4.624,11.916,10.757,13.147c-1.124,0.308-2.311,0.471-3.532,0.471c-0.866,0-1.705-0.083-2.523-0.239 c1.706,5.326,6.657,9.203,12.526,9.312c-4.59,3.597-10.371,5.74-16.655,5.74c-1.08,0-2.15-0.063-3.197-0.188 c5.931,3.806,12.981,6.025,20.553,6.025c24.664,0,38.152-20.432,38.152-38.153c0-0.581-0.013-1.16-0.039-1.734 C86.391,45.366,88.664,43.005,90.461,40.316L90.461,40.316z"/></svg> | |||
| @@ -2,5 +2,8 @@ module.exports = function(api) { | |||
| api.cache(true); | |||
| return { | |||
| presets: ['babel-preset-expo'], | |||
| plugins: [ | |||
| 'react-native-reanimated/plugin' | |||
| ] | |||
| }; | |||
| }; | |||
| @@ -0,0 +1,30 @@ | |||
| import React from 'react'; | |||
| import { StyleSheet, Text, TouchableOpacity } from 'react-native'; | |||
| const CustomButton = ({label, onPress}) => { | |||
| return ( | |||
| <TouchableOpacity onPress={onPress} style={styles.button}> | |||
| <Text style={styles.buttonText}> | |||
| {label} | |||
| </Text> | |||
| </TouchableOpacity> | |||
| ) | |||
| } | |||
| const styles = StyleSheet.create({ | |||
| button: { | |||
| backgroundColor: '#AD40AF', | |||
| padding: 20, | |||
| borderRadius: 10, | |||
| marginBottom: 30 | |||
| }, | |||
| buttonText: { | |||
| textAlign: 'center', | |||
| fontWeight: '700', | |||
| fontSize: 16, | |||
| color: '#fff', | |||
| fontFamily: 'poppins-semibold' | |||
| } | |||
| }) | |||
| export default CustomButton; | |||
| @@ -0,0 +1,86 @@ | |||
| import React, {useContext} from 'react'; | |||
| import { View, Text, ImageBackground, Image, TouchableOpacity, StyleSheet, Linking } from 'react-native'; | |||
| import { DrawerContentScrollView, DrawerItemList } from '@react-navigation/drawer'; | |||
| import { AuthContext } from '../../context/AuthContext'; | |||
| import Spinner from 'react-native-loading-spinner-overlay/lib'; | |||
| import Loader from '../Loader'; | |||
| const CustomDrawer = props => { | |||
| const {logout, isLoading} = useContext(AuthContext); | |||
| return ( | |||
| <View style={styles.container}> | |||
| <Loader visible={isLoading} /> | |||
| <DrawerContentScrollView {...props} contentContainerStyle={styles.drawer}> | |||
| <ImageBackground source={require('../../assets/images/menu-bg.jpeg')} style={styles.backgroundImage}> | |||
| <Image source={require('../../assets/images/diligent-purple.png')} style={styles.profileImage} /> | |||
| <Text style={styles.userName}>Diligent Software</Text> | |||
| </ImageBackground> | |||
| <View style={styles.drawerItems}> | |||
| <DrawerItemList {...props} /> | |||
| </View> | |||
| </DrawerContentScrollView> | |||
| <View style={styles.footer}> | |||
| <TouchableOpacity onPress={() => Linking.openURL('mailto:office@dilig.net')} style={styles.footerButton}> | |||
| <View style={styles.buttonContent}> | |||
| <Text style={styles.footerButtonText}>Contact Us</Text> | |||
| </View> | |||
| </TouchableOpacity> | |||
| <TouchableOpacity onPress={logout} style={styles.footerButton}> | |||
| <View style={styles.buttonContent}> | |||
| <Text style={styles.footerButtonText}>Sign Out</Text> | |||
| </View> | |||
| </TouchableOpacity> | |||
| </View> | |||
| </View> | |||
| ) | |||
| } | |||
| const styles = StyleSheet.create({ | |||
| container: { | |||
| flex: 1 | |||
| }, | |||
| drawer: { | |||
| backgroundColor: '#8200d6' | |||
| }, | |||
| backgroundImage: { | |||
| padding: 20 | |||
| }, | |||
| profileImage: { | |||
| height: 80, | |||
| width: 80, | |||
| borderRadius: 40, | |||
| marginBottom: 10 | |||
| }, | |||
| userName: { | |||
| color: '#fff', | |||
| fontSize: 18, | |||
| marginBottom: 5, | |||
| fontFamily: 'poppins-regular' | |||
| }, | |||
| drawerItems: { | |||
| flex: 1, | |||
| backgroundColor: '#fff', | |||
| paddingTop: 10, | |||
| }, | |||
| footer: { | |||
| padding: 20, | |||
| borderTopWidth: 1, | |||
| borderTopColor: '#ccc' | |||
| }, | |||
| footerButton: { | |||
| paddingVertical: 15 | |||
| }, | |||
| buttonContent: { | |||
| flexDirection: 'row', | |||
| alignItems: 'center' | |||
| }, | |||
| footerButtonText: { | |||
| fontSize: 15, | |||
| marginLeft: 5, | |||
| fontFamily: 'poppins-regular' | |||
| } | |||
| }) | |||
| export default CustomDrawer; | |||
| @@ -0,0 +1,72 @@ | |||
| import React from "react"; | |||
| import { | |||
| View, | |||
| Text, | |||
| TouchableOpacity, | |||
| TextInput, | |||
| StyleSheet, | |||
| } from "react-native"; | |||
| import { globalStyles } from "../styles/global"; | |||
| const InputField = ({ | |||
| label, | |||
| icon, | |||
| inputType, | |||
| keyboardType, | |||
| filedButtonLabel, | |||
| fieldButtonFunction, | |||
| onChangeText, | |||
| text | |||
| }) => { | |||
| return ( | |||
| <View style={styles.textField}> | |||
| {icon} | |||
| {inputType === "password" ? ( | |||
| <TextInput | |||
| placeholder={label} | |||
| keyboardType={keyboardType} | |||
| style={styles.textInput} | |||
| secureTextEntry={true} | |||
| value={text} | |||
| onChangeText={inputText => { | |||
| if (onChangeText) { | |||
| onChangeText(inputText); | |||
| } | |||
| }} | |||
| /> | |||
| ) : ( | |||
| <TextInput | |||
| placeholder={label} | |||
| keyboardType={keyboardType} | |||
| style={styles.textInput} | |||
| value={text} | |||
| onChangeText={inputText => { | |||
| if (onChangeText) { | |||
| onChangeText(inputText); | |||
| } | |||
| }} | |||
| /> | |||
| )} | |||
| <TouchableOpacity onPress={fieldButtonFunction}> | |||
| <Text style={globalStyles.primaryBold}>{filedButtonLabel}</Text> | |||
| </TouchableOpacity> | |||
| </View> | |||
| ); | |||
| }; | |||
| const styles = StyleSheet.create({ | |||
| textField: { | |||
| flexDirection: "row", | |||
| borderBottomColor: "#ccc", | |||
| borderBottomWidth: 1, | |||
| paddingBottom: 8, | |||
| marginBottom: 25, | |||
| }, | |||
| textInput: { | |||
| flex: 1, | |||
| paddingVertical: 0, | |||
| fontFamily: "poppins-regular", | |||
| }, | |||
| }); | |||
| export default InputField; | |||
| @@ -0,0 +1,15 @@ | |||
| import React from "react"; | |||
| import { PulseIndicator } from "react-native-indicators"; | |||
| import Spinner from "react-native-loading-spinner-overlay/lib"; | |||
| const Loader = ({visible}) => { | |||
| return ( | |||
| <Spinner | |||
| color="#AD40AF" | |||
| visible={visible} | |||
| customIndicator={<PulseIndicator color="#AD40AF" />} | |||
| /> | |||
| ); | |||
| }; | |||
| export default Loader; | |||
| @@ -0,0 +1,115 @@ | |||
| import AsyncStorage from "@react-native-async-storage/async-storage"; | |||
| import * as Google from "expo-auth-session/providers/google"; | |||
| import React, { createContext, useEffect, useState } from "react"; | |||
| import { googleApi, loginApi, registerApi } from "../service/user"; | |||
| export const AuthContext = createContext(); | |||
| export const AuthProvider = ({ children }) => { | |||
| const [userInfo, setUserInfo] = useState({}); | |||
| const [isLoading, setIsLoading] = useState(false); | |||
| // Google Auth | |||
| const [request, response, promptAsync] = Google.useAuthRequest({ | |||
| androidClientId: | |||
| "1032296921439-dpgvgkss3ggds0egvo6puf0r7un9em6c.apps.googleusercontent.com", | |||
| iosClientId: | |||
| "1032296921439-j7jfahhm7q3l07aj04qvdblmcns77oul.apps.googleusercontent.com", | |||
| expoClientId: | |||
| "1032296921439-vfs9k28sn7kei4nft998ck3067m8ksiq.apps.googleusercontent.com", | |||
| }); | |||
| useEffect(() => { | |||
| if (response?.type === "success") { | |||
| googleApi(response.authentication.accessToken) | |||
| .then((res) => { | |||
| if (res.user) { | |||
| setUserInfo(res); | |||
| AsyncStorage.setItem("userInfo", JSON.stringify(res)); | |||
| setIsLoading(false); | |||
| } else { | |||
| callback(res); | |||
| setIsLoading(false); | |||
| } | |||
| }) | |||
| .catch((e) => { | |||
| console.log("error", e); | |||
| setIsLoading(false); | |||
| }); | |||
| } | |||
| }, [response]); | |||
| const login = (email, password, callback) => { | |||
| setIsLoading(true); | |||
| loginApi({ identifier: email, password }) | |||
| .then((res) => { | |||
| if (res.user) { | |||
| setUserInfo(res); | |||
| AsyncStorage.setItem("userInfo", JSON.stringify(res)); | |||
| setIsLoading(false); | |||
| } else { | |||
| callback(res); | |||
| setIsLoading(false); | |||
| } | |||
| }) | |||
| .catch((e) => { | |||
| console.log("error", e); | |||
| setIsLoading(false); | |||
| }); | |||
| }; | |||
| const googleAuth = () => { | |||
| promptAsync({ useProxy: false, showInRecents: true }); | |||
| }; | |||
| const register = (username, email, password, callback) => { | |||
| setIsLoading(true); | |||
| registerApi({ username, email, password }) | |||
| .then((res) => { | |||
| if (res.user) { | |||
| setUserInfo(res); | |||
| AsyncStorage.setItem("userInfo", JSON.stringify(res)); | |||
| setIsLoading(false); | |||
| } else { | |||
| callback(res); | |||
| setIsLoading(false); | |||
| } | |||
| }) | |||
| .catch((e) => { | |||
| console.log("error", e); | |||
| setIsLoading(false); | |||
| }); | |||
| }; | |||
| const logout = () => { | |||
| setIsLoading(true); | |||
| AsyncStorage.removeItem("userInfo"); | |||
| setUserInfo({}); | |||
| setIsLoading(false); | |||
| }; | |||
| const isLoggedIn = async () => { | |||
| try { | |||
| let userInfo = await AsyncStorage.getItem("userInfo"); | |||
| userInfo = JSON.parse(userInfo); | |||
| if (userInfo) { | |||
| setUserInfo(userInfo); | |||
| } | |||
| } catch (e) { | |||
| console.log(e); | |||
| } | |||
| }; | |||
| useEffect(() => { | |||
| isLoggedIn(); | |||
| }, []); | |||
| return ( | |||
| <AuthContext.Provider | |||
| value={{ isLoading, login, logout, userInfo, register, googleAuth }} | |||
| > | |||
| {children} | |||
| </AuthContext.Provider> | |||
| ); | |||
| }; | |||
| @@ -0,0 +1,26 @@ | |||
| { | |||
| "cli": { | |||
| "version": ">= 3.0.0" | |||
| }, | |||
| "build": { | |||
| "development": { | |||
| "developmentClient": true, | |||
| "distribution": "internal", | |||
| "ios": { | |||
| "simulator": true | |||
| } | |||
| }, | |||
| "test": { | |||
| "android": { | |||
| "buildType": "apk" | |||
| } | |||
| }, | |||
| "preview": { | |||
| "distribution": "internal" | |||
| }, | |||
| "production": {} | |||
| }, | |||
| "submit": { | |||
| "production": {} | |||
| } | |||
| } | |||
| @@ -0,0 +1,8 @@ | |||
| import { registerRootComponent } from 'expo'; | |||
| import App from './App'; | |||
| // registerRootComponent calls AppRegistry.registerComponent('main', () => App); | |||
| // It also ensures that whether you load the app in Expo Go or in a native build, | |||
| // the environment is set up appropriately | |||
| registerRootComponent(App); | |||
| @@ -0,0 +1,45 @@ | |||
| import React from 'react'; | |||
| import { createDrawerNavigator } from '@react-navigation/drawer'; | |||
| import CustomDrawer from '../components/CustomDrawer/CustomDrawer'; | |||
| import TabNavigator from './TabNavigator'; | |||
| import Ionicons from '@expo/vector-icons/Ionicons'; | |||
| import SettingsScreen from '../screens/SettingsScreen'; | |||
| import ProfileScreen from '../screens/ProfileScreen'; | |||
| const Drawer = createDrawerNavigator(); | |||
| const AppStack = () => { | |||
| return ( | |||
| <Drawer.Navigator drawerContent={props => <CustomDrawer {...props} />} | |||
| screenOptions={{ | |||
| headerShown: false, | |||
| drawerActiveBackgroundColor: '#aa18ea', | |||
| drawerActiveTintColor: '#fff', | |||
| drawerInactiveTintColor: '#333', | |||
| drawerLabelStyle: { | |||
| marginLeft: 5, | |||
| fontSize: 16 | |||
| } | |||
| }} | |||
| > | |||
| <Drawer.Screen name='Home' component={TabNavigator} options={{ | |||
| drawerIcon: ({color}) => ( | |||
| <Ionicons name='home-outline' size={22} color={color} /> | |||
| ) | |||
| }} /> | |||
| <Drawer.Screen name='Profile' component={ProfileScreen} options={{ | |||
| drawerIcon: ({color}) => ( | |||
| <Ionicons name='person-outline' size={22} color={color} /> | |||
| ) | |||
| }} /> | |||
| <Drawer.Screen name='Settings' component={SettingsScreen} options={{ | |||
| drawerIcon: ({color}) => ( | |||
| <Ionicons name='settings-outline' size={22} color={color} /> | |||
| ) | |||
| }} /> | |||
| </Drawer.Navigator> | |||
| ) | |||
| } | |||
| export default AppStack; | |||
| @@ -0,0 +1,21 @@ | |||
| import React from 'react'; | |||
| import { createNativeStackNavigator } from '@react-navigation/native-stack'; | |||
| import OnboardingScreen from '../screens/OnboardingScreen'; | |||
| import LoginScreen from '../screens/LoginScreen'; | |||
| import RegisterScreen from '../screens/RegisterScreen'; | |||
| const Stack = createNativeStackNavigator(); | |||
| const AuthStack = () => { | |||
| return ( | |||
| <Stack.Navigator screenOptions={{headerShown: false}}> | |||
| <Stack.Screen name='Onboarding' component={OnboardingScreen} /> | |||
| <Stack.Screen name='Login' component={LoginScreen} /> | |||
| <Stack.Screen name='Register' component={RegisterScreen} /> | |||
| </Stack.Navigator> | |||
| ) | |||
| } | |||
| export default AuthStack; | |||
| @@ -0,0 +1,15 @@ | |||
| import React, {useContext} from 'react' | |||
| import { AuthContext } from '../context/AuthContext' | |||
| import AppStack from './AppStack'; | |||
| import AuthStack from './AuthStack'; | |||
| const RootNavigation = () => { | |||
| const {userInfo} = useContext(AuthContext); | |||
| return ( | |||
| !userInfo.jwt ? <AuthStack /> : <AppStack /> | |||
| ) | |||
| } | |||
| export default RootNavigation | |||
| @@ -0,0 +1,71 @@ | |||
| import React from "react"; | |||
| import { createNativeStackNavigator } from "@react-navigation/native-stack"; | |||
| import { createBottomTabNavigator } from "@react-navigation/bottom-tabs"; | |||
| import { getFocusedRouteNameFromRoute } from "@react-navigation/native"; | |||
| import HomeScreen from "../screens/HomeScreen"; | |||
| import Ionicons from "@expo/vector-icons/Ionicons"; | |||
| import FavoriteScreen from "../screens/FavoriteScreen"; | |||
| const Tab = createBottomTabNavigator(); | |||
| const Stack = createNativeStackNavigator(); | |||
| const HomeStack = () => { | |||
| return ( | |||
| <Stack.Navigator> | |||
| <Stack.Screen | |||
| name="Home" | |||
| component={HomeScreen} | |||
| options={{ headerShown: false }} | |||
| /> | |||
| </Stack.Navigator> | |||
| ); | |||
| }; | |||
| const TabNavigator = () => { | |||
| return ( | |||
| <Tab.Navigator | |||
| screenOptions={{ | |||
| headerShown: false, | |||
| tabBarShowLabel: false, | |||
| tabBarStyle: { backgroundColor: "#AD40AF" }, | |||
| tabBarInactiveTintColor: "#fff", | |||
| tabBarActiveTintColor: "yellow", | |||
| }} | |||
| > | |||
| <Tab.Screen | |||
| name="Home2" | |||
| component={HomeStack} | |||
| options={({ route }) => ({ | |||
| tabBarStyle: { | |||
| display: getTabBarVisibility(route), | |||
| backgroundColor: "#AD40AF", | |||
| }, | |||
| tabBarIcon: ({ color, size }) => ( | |||
| <Ionicons name="home-outline" color={color} size={size} /> | |||
| ), | |||
| })} | |||
| /> | |||
| <Tab.Screen | |||
| name="Favorite" | |||
| component={FavoriteScreen} | |||
| options={{ | |||
| tabBarIcon: ({ color, size }) => ( | |||
| <Ionicons name="heart-outline" color={color} size={size} /> | |||
| ), | |||
| }} | |||
| /> | |||
| </Tab.Navigator> | |||
| ); | |||
| }; | |||
| const getTabBarVisibility = (route) => { | |||
| const routeName = getFocusedRouteNameFromRoute(route) ?? "Feed"; | |||
| if (routeName === "Details") { | |||
| return "none"; | |||
| } | |||
| return "flex"; | |||
| }; | |||
| export default TabNavigator; | |||
| @@ -1,40 +1,51 @@ | |||
| { | |||
| "main": "node_modules/expo/AppEntry.js", | |||
| "scripts": { | |||
| "start": "expo start", | |||
| "android": "expo start --android", | |||
| "ios": "expo start --ios", | |||
| "start": "expo start --dev-client", | |||
| "android": "expo run:android", | |||
| "ios": "expo run:ios", | |||
| "web": "expo start --web", | |||
| "eject": "expo eject" | |||
| }, | |||
| "dependencies": { | |||
| "@react-native-async-storage/async-storage": "~1.17.3", | |||
| "@react-native-community/datetimepicker": "6.5.2", | |||
| "@react-native-google-signin/google-signin": "^8.2.2", | |||
| "@react-native-masked-view/masked-view": "0.2.8", | |||
| "@react-navigation/bottom-tabs": "^6.4.3", | |||
| "@react-navigation/drawer": "^6.5.5", | |||
| "@react-navigation/native": "^6.0.16", | |||
| "@react-navigation/native-stack": "^6.9.4", | |||
| "@reduxjs/toolkit": "^1.9.1", | |||
| "axios": "^1.2.1", | |||
| "expo": "^47.0.8", | |||
| "expo": "~47.0.8", | |||
| "expo-auth-session": "~3.7.3", | |||
| "expo-random": "~13.0.0", | |||
| "expo-status-bar": "~1.4.2", | |||
| "expo-web-browser": "~12.0.0", | |||
| "react": "18.1.0", | |||
| "react-dom": "18.1.0", | |||
| "react-native": "0.70.5", | |||
| "react-native-gesture-handler": "~2.8.0", | |||
| "react-native-indicators": "^0.17.0", | |||
| "react-native-loading-spinner-overlay": "^3.0.1", | |||
| "react-native-reanimated": "~2.12.0", | |||
| "react-native-responsive-screen": "^1.4.2", | |||
| "react-native-safe-area-context": "4.4.1", | |||
| "react-native-screens": "~3.18.0", | |||
| "react-native-svg": "13.4.0", | |||
| "react-native-svg-transformer": "^1.0.0", | |||
| "react-native-vector-icons": "^9.2.0", | |||
| "react-native-web": "~0.18.7", | |||
| "react-navigation-stack": "^2.10.4", | |||
| "react-redux": "^8.0.5", | |||
| "redux-batched-actions": "^0.5.0", | |||
| "redux-thunk": "^2.4.2" | |||
| "redux-thunk": "^2.4.2", | |||
| "expo-splash-screen": "~0.17.5" | |||
| }, | |||
| "devDependencies": { | |||
| "@babel/core": "^7.19.3" | |||
| }, | |||
| "private": true | |||
| "private": true, | |||
| "name": "diligent-react-native", | |||
| "version": "1.0.0" | |||
| } | |||
| @@ -1,49 +0,0 @@ | |||
| import React from "react"; | |||
| import { StyleSheet, Text, TouchableOpacity, View } from "react-native"; | |||
| import { useDispatch, useSelector } from "react-redux"; | |||
| import { decrement, increment } from "../store/actions"; | |||
| export const Counter = () => { | |||
| const dispatch = useDispatch() | |||
| const value = useSelector(s => s.test.value) | |||
| return ( | |||
| <View style={[{ width: '75%' }]}> | |||
| <Text style={[styles.textAlignCenter]}>{value}</Text> | |||
| <View style={[styles.row, styles.justifySpaceBetween]}> | |||
| <TouchableOpacity style={[styles.button, styles.justifyCenter]} onPress={() => dispatch(increment())}> | |||
| <Text style={[styles.textAlignCenter]}>Increment</Text> | |||
| </TouchableOpacity> | |||
| <TouchableOpacity style={[styles.button, styles.justifyCenter]} onPress={() => dispatch(decrement())}> | |||
| <Text style={[styles.textAlignCenter]}>Decrement</Text> | |||
| </TouchableOpacity> | |||
| </View> | |||
| </View> | |||
| ) | |||
| } | |||
| const styles = StyleSheet.create({ | |||
| row: { | |||
| flexDirection: "row", | |||
| }, | |||
| flex: { | |||
| flex: 1 | |||
| }, | |||
| justifySpaceBetween: { | |||
| justifyContent: 'space-between' | |||
| }, | |||
| button: { | |||
| backgroundColor: "#D9F1EC", | |||
| padding: '3%', | |||
| marginTop: '10%' | |||
| }, | |||
| textAlignCenter: { | |||
| textAlign: 'center' | |||
| }, | |||
| justifyCenter: { | |||
| justifyContent: 'center' | |||
| }, | |||
| alignCenter: { | |||
| alignItems: 'center' | |||
| } | |||
| }) | |||
| @@ -0,0 +1,20 @@ | |||
| import React from 'react'; | |||
| import { View, Text, StyleSheet } from 'react-native'; | |||
| const FavoriteScreen = () => { | |||
| return ( | |||
| <View style={styles.container}> | |||
| <Text>Favorite</Text> | |||
| </View> | |||
| ) | |||
| } | |||
| const styles = StyleSheet.create({ | |||
| container: { | |||
| flex: 1, | |||
| justifyContent: 'center', | |||
| alignItems: 'center' | |||
| } | |||
| }) | |||
| export default FavoriteScreen; | |||
| @@ -0,0 +1,36 @@ | |||
| import React from 'react'; | |||
| import { View, Text, SafeAreaView, ScrollView, ImageBackground, TextInput, TouchableOpacity, StyleSheet } from 'react-native'; | |||
| import Feather from '@expo/vector-icons/Feather'; | |||
| import { windowWidth } from '../utils/Dimensions'; | |||
| const HomeScreen = ({navigation}) => { | |||
| return ( | |||
| <SafeAreaView style={{flex: 1, backgroundColor: '#fff'}}> | |||
| <ScrollView style={{padding: 20}}> | |||
| <View style={styles.wrapper}> | |||
| <Text style={{fontSize: 18}}> | |||
| Hello Diligent | |||
| </Text> | |||
| <TouchableOpacity onPress={() => navigation.openDrawer()}> | |||
| <ImageBackground source={require('../assets/images/diligent-purple.png')} style={styles.imageBackground} imageStyle={{borderRadius:25}} /> | |||
| </TouchableOpacity> | |||
| </View> | |||
| </ScrollView> | |||
| </SafeAreaView> | |||
| ) | |||
| } | |||
| const styles = StyleSheet.create({ | |||
| wrapper: { | |||
| flexDirection: 'row', | |||
| justifyContent: 'space-between', | |||
| marginBottom: 20 | |||
| }, | |||
| imageBackground: { | |||
| width: 35, | |||
| height: 35 | |||
| } | |||
| }) | |||
| export default HomeScreen; | |||
| @@ -1,66 +0,0 @@ | |||
| import React from "react"; | |||
| import { useState } from "react"; | |||
| import { View, TextInput, Text, StyleSheet } from "react-native"; | |||
| import Button from "../components/Buttons/Button"; | |||
| import { login } from "../thunks/user.thunk"; | |||
| import { useDispatch } from "react-redux"; | |||
| export const LogIn = () => { | |||
| const [username, setUsername] = useState() | |||
| const [password, setPassword] = useState() | |||
| const [error, setError] = useState() | |||
| const dispatch = useDispatch(); | |||
| const loginHandler = () => { | |||
| dispatch( | |||
| login(username, password, function (result) { | |||
| console.log(result.data) | |||
| if (!result.OK) { | |||
| setUsername(""); | |||
| setPassword(""); | |||
| setError(result.data.Message ? result.data.Message : "Error occurred during Login,please try again!"); | |||
| } | |||
| }) | |||
| ) | |||
| } | |||
| return ( | |||
| <View style={{flex: 1, justifyContent: 'center'}}> | |||
| <Text style={styles.errorMessage}>{error && error}</Text> | |||
| <TextInput focus={true} | |||
| style={styles.input} | |||
| placeholder='Username' | |||
| placeholderTextColor='#000' | |||
| value={username} | |||
| onChangeText={setUsername} | |||
| /> | |||
| <TextInput focus={true} | |||
| style={styles.input} | |||
| placeholder='Password' | |||
| placeholderTextColor='#000' | |||
| value={password} | |||
| onChangeText={setPassword} | |||
| secureTextEntry /> | |||
| <Button | |||
| onPress={loginHandler} | |||
| title='Log In' | |||
| style={{ margin: 12, backgroundColor: '#3E5076' }} | |||
| /> | |||
| </View> | |||
| ) | |||
| } | |||
| const styles = StyleSheet.create({ | |||
| input: { | |||
| height: 40, | |||
| margin: 12, | |||
| borderWidth: 1, | |||
| padding: 10, | |||
| borderRadius: 5 | |||
| }, | |||
| errorMessage: { | |||
| color: 'red', | |||
| margin: 12 | |||
| } | |||
| }); | |||
| @@ -0,0 +1,132 @@ | |||
| import React, {useState, useContext} from "react"; | |||
| import { | |||
| SafeAreaView, | |||
| View, | |||
| Text, | |||
| TouchableOpacity, | |||
| StyleSheet, | |||
| } from "react-native"; | |||
| import MaterialIcons from "@expo/vector-icons/MaterialIcons"; | |||
| import Ionicons from "@expo/vector-icons/Ionicons"; | |||
| import LoginSVG from "../assets/images/login.svg"; | |||
| import GoogleSVG from "../assets/images/google.svg"; | |||
| import FacebookSVG from "../assets/images/facebook.svg"; | |||
| import TwitterSVG from "../assets/images/twitter.svg"; | |||
| import CustomButton from "../components/Buttons/CustomButton"; | |||
| import InputField from "../components/InputField"; | |||
| import { globalStyles } from "../styles/global"; | |||
| import { AuthContext } from "../context/AuthContext"; | |||
| import Loader from "../components/Loader"; | |||
| const LoginScreen = ({ navigation }) => { | |||
| const [email, setEmail] = useState(null); | |||
| const [password, setPassword] = useState(null); | |||
| const [error, setError] = useState(null); | |||
| const {isLoading, login, googleAuth} = useContext(AuthContext); | |||
| const handleLogin = () => { | |||
| login(email, password, function(result) { | |||
| setError(result.error.message); | |||
| }); | |||
| } | |||
| return ( | |||
| <SafeAreaView style={globalStyles.safeArea}> | |||
| <Loader visible={isLoading} /> | |||
| <View style={{ paddingHorizontal: 25 }}> | |||
| <View style={{ alignItems: "center" }}> | |||
| <LoginSVG height={300} width={300} /> | |||
| </View> | |||
| <Text style={globalStyles.boldText}>Sign In</Text> | |||
| <InputField | |||
| label={"Email"} | |||
| keyboardType="email-address" | |||
| onChangeText={text => { | |||
| setEmail(text); | |||
| }} | |||
| text={email} | |||
| icon={ | |||
| <MaterialIcons | |||
| name="alternate-email" | |||
| size={20} | |||
| color="#666" | |||
| style={{ marginRight: 5 }} | |||
| /> | |||
| } | |||
| /> | |||
| <InputField | |||
| label={"Password"} | |||
| filedButtonLabel={"Forgot?"} | |||
| fieldButtonFunction={() => {}} | |||
| inputType="password" | |||
| text={password} | |||
| onChangeText={text => { | |||
| setPassword(text); | |||
| }} | |||
| icon={ | |||
| <Ionicons | |||
| name="ios-lock-closed-outline" | |||
| size={20} | |||
| color="#666" | |||
| style={{ marginRight: 5 }} | |||
| /> | |||
| } | |||
| /> | |||
| {error && <Text style={styles.errorMessage}>{error}</Text>} | |||
| <CustomButton label={"Login"} onPress={handleLogin} /> | |||
| <Text style={globalStyles.regularCenteredText}>Or login with ...</Text> | |||
| <View style={styles.providersContainer}> | |||
| <TouchableOpacity onPress={googleAuth} style={globalStyles.iconButton}> | |||
| <GoogleSVG height={24} width={24} /> | |||
| </TouchableOpacity> | |||
| <TouchableOpacity onPress={() => {}} style={globalStyles.iconButton}> | |||
| <FacebookSVG height={24} width={24} /> | |||
| </TouchableOpacity> | |||
| <TouchableOpacity onPress={() => {}} style={globalStyles.iconButton}> | |||
| <TwitterSVG height={24} width={24} /> | |||
| </TouchableOpacity> | |||
| </View> | |||
| <View style={styles.registerContainer}> | |||
| <Text style={globalStyles.regularText}>Need account? </Text> | |||
| <TouchableOpacity onPress={() => navigation.navigate("Register")}> | |||
| <Text style={styles.registerButtonText}>Sign Up</Text> | |||
| </TouchableOpacity> | |||
| </View> | |||
| </View> | |||
| </SafeAreaView> | |||
| ); | |||
| }; | |||
| const styles = StyleSheet.create({ | |||
| providerText: { | |||
| textAlign: "center", | |||
| color: "#666", | |||
| marginBottom: 30, | |||
| fontFamily: "poppins-regular", | |||
| }, | |||
| providersContainer: { | |||
| flexDirection: "row", | |||
| justifyContent: "space-between", | |||
| marginBottom: 30, | |||
| }, | |||
| registerContainer: { | |||
| flexDirection: "row", | |||
| justifyContent: "center", | |||
| marginBottom: 30, | |||
| }, | |||
| registerButtonText: { | |||
| color: "#AD40AF", | |||
| fontWeight: "700", | |||
| fontFamily: "poppins-semibold", | |||
| }, | |||
| errorMessage: { | |||
| marginBottom: 30, | |||
| color: 'red' | |||
| } | |||
| }); | |||
| export default LoginScreen; | |||
| @@ -0,0 +1,58 @@ | |||
| import React from 'react'; | |||
| import { SafeAreaView, View, Text, TouchableOpacity, StyleSheet, Image } from 'react-native'; | |||
| import MaterialIcons from '@expo/vector-icons/MaterialIcons'; | |||
| const OnboardingScreen = ({navigation}) => { | |||
| return ( | |||
| <SafeAreaView style={styles.safeArea}> | |||
| <View style={{marginTop: 20}}> | |||
| <Text style={styles.headText}>DILIGENT</Text> | |||
| </View> | |||
| <View style={styles.logo}> | |||
| <Image style={{width: 300, height: 300}} source={require('../assets/images/diligent-logo.png')} /> | |||
| </View> | |||
| <TouchableOpacity style={styles.button} onPress={() => navigation.navigate('Login')}> | |||
| <Text style={styles.buttonText}>Let's begin</Text> | |||
| <MaterialIcons name='arrow-forward-ios' size={22} color='#fff' /> | |||
| </TouchableOpacity> | |||
| </SafeAreaView> | |||
| ) | |||
| } | |||
| const styles = StyleSheet.create({ | |||
| safeArea: { | |||
| flex: 1, | |||
| justifyContent: 'center', | |||
| alignItems: 'center', | |||
| backgroundColor: '#fff' | |||
| }, | |||
| headText: { | |||
| fontWeight: 'bold', | |||
| fontSize: 30, | |||
| color: '#20315f', | |||
| fontFamily: 'poppins-semibold' | |||
| }, | |||
| logo: { | |||
| flex: 1, | |||
| justifyContent: 'center', | |||
| alignItems: 'center' | |||
| }, | |||
| button: { | |||
| backgroundColor: '#AD40AF', | |||
| padding: 20, | |||
| width: '90%', | |||
| borderRadius: 10, | |||
| marginBottom: 50, | |||
| flexDirection: 'row', | |||
| justifyContent: 'space-between' | |||
| }, | |||
| buttonText: { | |||
| color: 'white', | |||
| fontSize: 18, | |||
| textAlign: 'center', | |||
| fontWeight: 'bold', | |||
| fontFamily: 'poppins-regular' | |||
| } | |||
| }) | |||
| export default OnboardingScreen; | |||
| @@ -0,0 +1,20 @@ | |||
| import React from 'react'; | |||
| import { View, Text, StyleSheet } from 'react-native'; | |||
| const ProfileScreen = () => { | |||
| return ( | |||
| <View style={styles.container}> | |||
| <Text>Profile</Text> | |||
| </View> | |||
| ) | |||
| } | |||
| const styles = StyleSheet.create({ | |||
| container: { | |||
| flex: 1, | |||
| justifyContent: 'center', | |||
| alignItems: 'center' | |||
| } | |||
| }) | |||
| export default ProfileScreen; | |||
| @@ -0,0 +1,197 @@ | |||
| import React, { useState, useContext } from "react"; | |||
| import { | |||
| SafeAreaView, | |||
| ScrollView, | |||
| View, | |||
| Text, | |||
| TextInput, | |||
| TouchableOpacity, | |||
| StyleSheet, | |||
| Platform, | |||
| } from "react-native"; | |||
| import DateTimePicker from "@react-native-community/datetimepicker"; | |||
| import InputField from "../components/InputField"; | |||
| import MaterialIcons from "@expo/vector-icons/MaterialIcons"; | |||
| import Ionicons from "@expo/vector-icons/Ionicons"; | |||
| import RegistrationSVG from "../assets/images/registration.svg"; | |||
| import GoogleSVG from "../assets/images/google.svg"; | |||
| import FacebookSVG from "../assets/images/facebook.svg"; | |||
| import TwitterSVG from "../assets/images/twitter.svg"; | |||
| import CustomButton from "../components/Buttons/CustomButton"; | |||
| import { globalStyles } from "../styles/global"; | |||
| import { AuthContext } from "../context/AuthContext"; | |||
| import Spinner from "react-native-loading-spinner-overlay/lib"; | |||
| import Loader from "../components/Loader"; | |||
| const RegisterScreen = ({ navigation }) => { | |||
| const { isLoading, register } = useContext(AuthContext); | |||
| const [date, setDate] = useState(new Date()); | |||
| const [open, setOpen] = useState(false); | |||
| const [dateOfBirthLabel, setDateOfBirthLabel] = useState("Date of Birth"); | |||
| const [username, setUsername] = useState(null); | |||
| const [email, setEmail] = useState(null); | |||
| const [password, setPassword] = useState(null); | |||
| const [confirmPassword, setConfirmPassword] = useState(null); | |||
| const [error, setError] = useState(null); | |||
| const onChange = (event, selectedDate) => { | |||
| const currentDate = selectedDate || date; | |||
| setDate(currentDate); | |||
| let tempDate = new Date(currentDate); | |||
| let fDate = | |||
| tempDate.getDate() + | |||
| "/" + | |||
| (tempDate.getMonth() + 1) + | |||
| "/" + | |||
| tempDate.getFullYear(); | |||
| setDateOfBirthLabel(fDate); | |||
| setOpen(false); | |||
| }; | |||
| const handleSignup = () => { | |||
| if (password !== confirmPassword) { | |||
| setError("Passwords must match"); | |||
| return; | |||
| } | |||
| register(username, email, password, function (result) { | |||
| setError(result.error.message); | |||
| }); | |||
| }; | |||
| return ( | |||
| <SafeAreaView style={globalStyles.safeArea}> | |||
| <Loader visible={isLoading} /> | |||
| <ScrollView | |||
| showsVerticalScrollIndicator={false} | |||
| style={{ paddingHorizontal: 25 }} | |||
| > | |||
| <View style={{ alignItems: "center" }}> | |||
| <RegistrationSVG width={300} height={300} /> | |||
| </View> | |||
| <Text style={globalStyles.boldText}>Sign Up</Text> | |||
| <View style={styles.providersContainer}> | |||
| <TouchableOpacity onPress={() => {}} style={globalStyles.iconButton}> | |||
| <GoogleSVG height={24} width={24} /> | |||
| </TouchableOpacity> | |||
| <TouchableOpacity onPress={() => {}} style={globalStyles.iconButton}> | |||
| <FacebookSVG height={24} width={24} /> | |||
| </TouchableOpacity> | |||
| <TouchableOpacity onPress={() => {}} style={globalStyles.iconButton}> | |||
| <TwitterSVG height={24} width={24} /> | |||
| </TouchableOpacity> | |||
| </View> | |||
| <Text style={globalStyles.regularCenteredText}> | |||
| Or, sign up with email... | |||
| </Text> | |||
| <InputField | |||
| text={username} | |||
| onChangeText={(text) => setUsername(text)} | |||
| label={"Full Name"} | |||
| icon={ | |||
| <Ionicons | |||
| name="person-outline" | |||
| size={20} | |||
| color="#666" | |||
| style={{ marginRight: 5 }} | |||
| /> | |||
| } | |||
| /> | |||
| <InputField | |||
| text={email} | |||
| onChangeText={(text) => setEmail(text)} | |||
| label={"Email"} | |||
| icon={ | |||
| <MaterialIcons | |||
| name="alternate-email" | |||
| size={20} | |||
| color="#666" | |||
| style={{ marginRight: 5 }} | |||
| /> | |||
| } | |||
| keyboardType="email-address" | |||
| /> | |||
| <InputField | |||
| text={password} | |||
| onChangeText={(text) => setPassword(text)} | |||
| label={"Password"} | |||
| icon={ | |||
| <Ionicons | |||
| name="ios-lock-closed-outline" | |||
| size={20} | |||
| color="#666" | |||
| style={{ marginRight: 5 }} | |||
| /> | |||
| } | |||
| inputType="password" | |||
| /> | |||
| <InputField | |||
| text={confirmPassword} | |||
| onChangeText={(text) => setConfirmPassword(text)} | |||
| label={"Confirm Password"} | |||
| icon={ | |||
| <Ionicons | |||
| name="ios-lock-closed-outline" | |||
| size={20} | |||
| color="#666" | |||
| style={{ marginRight: 5 }} | |||
| /> | |||
| } | |||
| inputType="password" | |||
| /> | |||
| {/* <View style={styles.dateOfBirthContainer}> | |||
| <Ionicons name='calendar-outline' size={20} color="#666" style={{marginRight: 5}} /> | |||
| <TouchableOpacity onPress={() => setOpen(true)}> | |||
| <Text style={styles.dateOfBirthLabel}>{dateOfBirthLabel}</Text> | |||
| {open && <DateTimePicker testID='dateTimePicker' value={date} mode="date" display='spinner' onChange={onChange} textColor="#000" />} | |||
| </TouchableOpacity> | |||
| </View> */} | |||
| {error && <Text style={styles.errorMessage}>{error}</Text>} | |||
| <CustomButton label={"Sign Up"} onPress={handleSignup} /> | |||
| <View style={styles.alreadyRegistered}> | |||
| <Text style={globalStyles.regularText}>Already Registered? </Text> | |||
| <TouchableOpacity onPress={() => navigation.goBack()}> | |||
| <Text style={globalStyles.primaryBold}>Sign In</Text> | |||
| </TouchableOpacity> | |||
| </View> | |||
| </ScrollView> | |||
| </SafeAreaView> | |||
| ); | |||
| }; | |||
| const styles = StyleSheet.create({ | |||
| providersContainer: { | |||
| flexDirection: "row", | |||
| justifyContent: "space-between", | |||
| marginBottom: 30, | |||
| }, | |||
| dateOfBirthContainer: { | |||
| flexDirection: "row", | |||
| borderBottomColor: "#ccc", | |||
| borderBottomWidth: 1, | |||
| paddingBottom: 8, | |||
| marginBottom: 30, | |||
| }, | |||
| dateOfBirthLabel: { | |||
| color: "#666", | |||
| marginLeft: 5, | |||
| marginTop: 5, | |||
| }, | |||
| alreadyRegistered: { | |||
| flexDirection: "row", | |||
| justifyContent: "center", | |||
| marginBottom: 30, | |||
| }, | |||
| errorMessage: { | |||
| marginBottom: 30, | |||
| color: "red", | |||
| }, | |||
| }); | |||
| export default RegisterScreen; | |||
| @@ -0,0 +1,20 @@ | |||
| import React from 'react'; | |||
| import { View, Text, StyleSheet } from 'react-native'; | |||
| const SettingsScreen = () => { | |||
| return ( | |||
| <View style={styles.container}> | |||
| <Text>Settings</Text> | |||
| </View> | |||
| ) | |||
| } | |||
| const styles = StyleSheet.create({ | |||
| container: { | |||
| flex: 1, | |||
| justifyContent: 'center', | |||
| alignItems: 'center' | |||
| } | |||
| }) | |||
| export default SettingsScreen; | |||
| @@ -0,0 +1,3 @@ | |||
| export default { | |||
| login: 'api/auth/local' | |||
| } | |||
| @@ -0,0 +1,26 @@ | |||
| import AsyncStorage from "@react-native-async-storage/async-storage"; | |||
| export const storeData = async (key, value) => { | |||
| try { | |||
| await AsyncStorage.setItem(key, value); | |||
| } catch (e) { | |||
| console.log(e); | |||
| } | |||
| } | |||
| export const getData = async (key) => { | |||
| try { | |||
| const value = await AsyncStorage.getItem(key); | |||
| return value; | |||
| } catch(e) { | |||
| // error reading value | |||
| } | |||
| } | |||
| export const removeData = async (key) => { | |||
| try { | |||
| await AsyncStorage.removeItem(key); | |||
| } catch(e) { | |||
| // error reading value | |||
| } | |||
| } | |||
| @@ -1 +1 @@ | |||
| export const API_ENDPOINT ="https://my.kalla.co/"; | |||
| export const API_ENDPOINT ="http://localhost:1337/"; | |||
| @@ -1,111 +1,41 @@ | |||
| import axios from "axios"; | |||
| import { setConnectionError } from "../store/actions"; | |||
| import store from "../store/index"; | |||
| import { API_ENDPOINT } from './endpointDef'; | |||
| import { refreshTokens } from "./tokenService/tokenApiClient"; | |||
| import { API_ENDPOINT } from "./endpointDef"; | |||
| const axiosApiInstance = axios.create(); | |||
| const globalLog = false; | |||
| const defaultOptions = { log: false } | |||
| export const Get = (url, options) => { | |||
| return request("GET", url, { ...defaultOptions, ...options }); | |||
| } | |||
| export const Post = (url, data, options) => { | |||
| return request("POST", url, { ...defaultOptions, ...options, data }); | |||
| } | |||
| export const Put = (url, data, options) => { | |||
| return request("PUT", url, { ...defaultOptions, ...options, data }); | |||
| } | |||
| export const Delete = (url, options) => { | |||
| return request("DELETE", url, { ...defaultOptions, ...options }); | |||
| } | |||
| const request = axios.create({ | |||
| baseURL: API_ENDPOINT, | |||
| headers: { | |||
| "Content-Type": "application/json", | |||
| }, | |||
| }); | |||
| const isLogging = (log) => { | |||
| return (globalLog || log); | |||
| } | |||
| export const getRequest = (url, params = null, options = null) => | |||
| request.get(url, { params, ...options }); | |||
| const request = (method, url, options) => { | |||
| const { data, log } = options; | |||
| if (isLogging(log)) console.log("REQUEST URL : ", url); | |||
| const requestObject = { | |||
| method, | |||
| url: API_ENDPOINT + url, | |||
| timeout: 60000 | |||
| } | |||
| if (data) { | |||
| if (isLogging(log)) console.log(`DATA FOR : ${url}`, data); | |||
| requestObject.data = data; | |||
| } | |||
| else { | |||
| requestObject.data = undefined; | |||
| } | |||
| // console.log("url", url) | |||
| return axiosApiInstance(requestObject).then((response) => { | |||
| if (isLogging(log)) console.log(`RESPONSE for ${url} : `, response); | |||
| export const postRequest = (url, data, params = null, options = null) => | |||
| request.post(url, data, { params, ...options }); | |||
| return { ...response, OK: true }; | |||
| }) | |||
| .catch((error) => { | |||
| if (isLogging(log)) console.log(`RESPONSE for catch ${url} : `, (error.response ? error.response : error)); | |||
| export const putRequest = (url, data, params = null, options = null) => | |||
| request.put(url, data, { params, ...options }); | |||
| //if we get a request timeout error | |||
| if (!error.response) { | |||
| store.dispatch(setConnectionError(error)); | |||
| return { error, OK: false }; | |||
| } | |||
| export const patchRequest = (url, data, params = null, options = null) => | |||
| request.patch(url, data, { params, ...options }); | |||
| //if we get a response other than OK | |||
| if (error.response) { | |||
| return { ...error.response, OK: false }; | |||
| } | |||
| export const deleteRequest = (url, params = null, options = null) => | |||
| request.delete(url, { params, ...options }); | |||
| return { OK: false }; | |||
| }) | |||
| } | |||
| export const addHeaderToken = (token) => { | |||
| request.defaults.headers.Authorization = `Bearer ${token}`; | |||
| }; | |||
| axiosApiInstance.interceptors.request.use( | |||
| (config) => { | |||
| // console.log('sending request') | |||
| const accessToken = store.getState().user.token; | |||
| config.headers = { | |||
| "Authorization": `Bearer ${accessToken}`, | |||
| "Accept": "application/json", | |||
| "Content-Type": "application/json", | |||
| "Referer": config.url | |||
| }; | |||
| return config; | |||
| }, | |||
| (error) => { | |||
| Promise.reject(error); | |||
| } | |||
| ); | |||
| export const removeHeaderToken = () => { | |||
| delete request.defaults.headers.Authorization; | |||
| }; | |||
| axiosApiInstance.interceptors.response.use( | |||
| (response) => { | |||
| return response; | |||
| }, | |||
| async (error) => { | |||
| // console.log('********************************************************************', error) | |||
| const originalRequest = error.config | |||
| if (originalRequest._retried) { | |||
| console.log("Request second attempt failed.") | |||
| } | |||
| if (!originalRequest._retried && error.response && error.response.status === 401) { | |||
| try { | |||
| await refreshTokens() | |||
| } | |||
| catch (e) { | |||
| throw error; | |||
| } | |||
| return await axiosApiInstance({ ...originalRequest, _retried: true }) | |||
| } | |||
| throw error; | |||
| } | |||
| ); | |||
| export const attachPostRequestListener = (postRequestListener) => { | |||
| request.interceptors.response.use( | |||
| (response) => response, | |||
| (response) => postRequestListener(response) | |||
| ); | |||
| }; | |||
| export default axiosApiInstance; | |||
| export const apiDefaultUrl = request.defaults.baseURL; | |||
| @@ -1,6 +1,39 @@ | |||
| import { Post } from './index'; | |||
| import { API_ENDPOINT } from "./endpointDef"; | |||
| export const loginApi = async (payload) => { | |||
| const result = await fetch(API_ENDPOINT + 'api/auth/local', { | |||
| method: 'POST', | |||
| headers: { | |||
| 'Content-Type': 'application/json' | |||
| }, | |||
| body: JSON.stringify(payload) | |||
| }) | |||
| const res = await result.json(); | |||
| return res; | |||
| }; | |||
| export const registerApi = async (payload) => { | |||
| const result = await fetch(API_ENDPOINT + 'api/auth/local/register', { | |||
| method: 'POST', | |||
| headers: { | |||
| 'Content-Type': 'application/json' | |||
| }, | |||
| body: JSON.stringify(payload) | |||
| }) | |||
| const res = await result.json(); | |||
| return res; | |||
| }; | |||
| export const googleApi = async (accessToken) => { | |||
| const result = await fetch('https://9dae-178-220-74-194.eu.ngrok.io/' + `api/auth/google/callback?access_token=${accessToken}`); | |||
| const res = await result.json(); | |||
| return res; | |||
| }; | |||
| export const loginAPI = async (username, password) => { | |||
| const body = JSON.stringify({ Username: username, Password: password }); | |||
| return Post(`api/login`, body); | |||
| }; | |||
| @@ -0,0 +1,44 @@ | |||
| import { StyleSheet } from "react-native"; | |||
| // Fonts | |||
| const regularFont = "poppins-regular"; | |||
| const semiBoldFont = "poppins-semibold"; | |||
| // Colors | |||
| const primary = "#AD40AF"; | |||
| const secondary = "#333"; | |||
| export const globalStyles = StyleSheet.create({ | |||
| boldText: { | |||
| fontSize: 28, | |||
| fontWeight: "500", | |||
| color: secondary, | |||
| marginBottom: 30, | |||
| fontFamily: semiBoldFont, | |||
| }, | |||
| primaryBold: { | |||
| color: primary, | |||
| fontWeight: "700", | |||
| fontFamily: semiBoldFont, | |||
| }, | |||
| iconButton: { | |||
| borderColor: "#ddd", | |||
| borderWidth: 2, | |||
| borderRadius: 10, | |||
| paddingHorizontal: 30, | |||
| paddingVertical: 10, | |||
| }, | |||
| regularText: { | |||
| fontFamily: regularFont, | |||
| }, | |||
| regularCenteredText: { | |||
| textAlign: "center", | |||
| color: "#666", | |||
| marginBottom: 30, | |||
| fontFamily: regularFont, | |||
| }, | |||
| safeArea: { | |||
| flex: 1, | |||
| justifyContent: "center", | |||
| }, | |||
| }); | |||
| @@ -1,19 +1,36 @@ | |||
| import { loginAPI } from "../service/user"; | |||
| import { setRefreshToken, setToken, setUsername } from "../store/actions"; | |||
| import { batchActions } from "redux-batched-actions"; | |||
| import { removeData, storeData } from "../service/asyncStorage"; | |||
| import { loginApi } from "../service/user"; | |||
| import { logInSuccess, setToken, setUsername } from "../store/actions"; | |||
| export const login = (username, password, callback) => { | |||
| return (dispatch) => | |||
| loginAPI(username, password) | |||
| .then((responseJson) => { | |||
| console.log('response', responseJson) | |||
| if (responseJson.OK && responseJson.data.Data.AccessToken != null) { | |||
| dispatch(batchActions([ | |||
| setToken(responseJson.data.Data.AccessToken), | |||
| setRefreshToken(responseJson.data.Data.RefreshToken), | |||
| setUsername(username)])) | |||
| } else callback(responseJson); | |||
| }) | |||
| .catch((error) => { | |||
| console.log("error", error); | |||
| }); | |||
| }; | |||
| export const login = (email, password, callback) => { | |||
| return async (dispatch) => { | |||
| const result = await loginApi({ identifier: email, password }); | |||
| if (result.data === null) { | |||
| callback(result); | |||
| }else { | |||
| await removeData("TOKEN"); | |||
| const token = await storeData('TOKEN', result.jwt); | |||
| console.log(result.user); | |||
| if (token) { | |||
| dispatch(batchActions([ | |||
| setToken(result.jwt), | |||
| setUsername(result.user.username), | |||
| logInSuccess(true) | |||
| ])) | |||
| } | |||
| } | |||
| }; | |||
| }; | |||
| export const logout = () => { | |||
| return async (dispatch) => { | |||
| await removeData('TOKEN'); | |||
| dispatch(batchActions([ | |||
| setToken(null), | |||
| setUsername(null), | |||
| logInSuccess(false) | |||
| ])) | |||
| }; | |||
| }; | |||
| @@ -0,0 +1,4 @@ | |||
| import { Dimensions } from "react-native"; | |||
| export const windowWidth = Dimensions.get('window').width; | |||
| export const windowHeight = Dimensions.get('window').height; | |||
| @@ -1193,6 +1193,20 @@ | |||
| slugify "^1.3.4" | |||
| sucrase "^3.20.0" | |||
| "@expo/configure-splash-screen@^0.6.0": | |||
| version "0.6.0" | |||
| resolved "https://registry.yarnpkg.com/@expo/configure-splash-screen/-/configure-splash-screen-0.6.0.tgz#07d97ee512fd859fcc09506ba3762fd6263ebc39" | |||
| integrity sha512-4DyPoNXJqx9bN4nEwF3HQreo//ECu7gDe1Xor3dnnzFm9P/VDxAKdbEhA0n+R6fgkNfT2onVHWijqvdpTS3Xew== | |||
| dependencies: | |||
| color-string "^1.5.3" | |||
| commander "^5.1.0" | |||
| fs-extra "^9.0.0" | |||
| glob "^7.1.6" | |||
| lodash "^4.17.15" | |||
| pngjs "^5.0.0" | |||
| xcode "^3.0.0" | |||
| xml-js "^1.6.11" | |||
| "@expo/dev-server@0.1.123": | |||
| version "0.1.123" | |||
| resolved "https://registry.yarnpkg.com/@expo/dev-server/-/dev-server-0.1.123.tgz#71304323b47db9ce300b9a774571ef2312b9d581" | |||
| @@ -1709,6 +1723,18 @@ | |||
| prompts "^2.4.0" | |||
| semver "^6.3.0" | |||
| "@react-native-community/datetimepicker@6.5.2": | |||
| version "6.5.2" | |||
| resolved "https://registry.yarnpkg.com/@react-native-community/datetimepicker/-/datetimepicker-6.5.2.tgz#d2c0df9f2c6acce39f7e957743dd811547656098" | |||
| integrity sha512-9K3zhIH1zmpIGSG3GJTWLIoAx+sR4kJ1wqpGKMwWJ5IYXBsFxMdvGw023t0pz2CQStlnNbbNhnZY/HMYFBCsCg== | |||
| dependencies: | |||
| invariant "^2.2.4" | |||
| "@react-native-google-signin/google-signin@^8.2.2": | |||
| version "8.2.2" | |||
| resolved "https://registry.yarnpkg.com/@react-native-google-signin/google-signin/-/google-signin-8.2.2.tgz#c8420fea36f05dfb067eb1fc301d42f442440a65" | |||
| integrity sha512-y56SDxupkN4nvIsmvnq11OqDMLJKTihbwT4dUtnPZ+FCOO4uX62zCpCyXub5o7/N12Ei8KCHC2umd8OHpMdRFg== | |||
| "@react-native-masked-view/masked-view@0.2.8": | |||
| version "0.2.8" | |||
| resolved "https://registry.yarnpkg.com/@react-native-masked-view/masked-view/-/masked-view-0.2.8.tgz#34405a4361882dae7c81b1b771fe9f5fbd545a97" | |||
| @@ -1755,6 +1781,20 @@ | |||
| react-is "^16.13.0" | |||
| use-latest-callback "^0.1.5" | |||
| "@react-navigation/drawer@^6.5.5": | |||
| version "6.5.5" | |||
| resolved "https://registry.yarnpkg.com/@react-navigation/drawer/-/drawer-6.5.5.tgz#7e65201435bd23d8418878210a670e8598337436" | |||
| integrity sha512-dkmbkv7nc7EWOqns6AlewTHIIAIa3RMwmzbucjqPBnJNJEv76YxUmYpiSQ8TBH9R3czA/Km6eGodyYmkP+3o5Q== | |||
| dependencies: | |||
| "@react-navigation/elements" "^1.3.11" | |||
| color "^4.2.3" | |||
| warn-once "^0.1.0" | |||
| "@react-navigation/elements@^1.3.11": | |||
| version "1.3.11" | |||
| resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.11.tgz#135c2cb3ae4a31bc835bb731110fd1ef9c38e237" | |||
| integrity sha512-o4J0g4ofJbbn68e4TpuGkuZLtq5mLll7Ndz9C4O4RvD2chchLuGQ5TycIPTKP428cz8JzuTCFqUe/ZhOPSsudw== | |||
| "@react-navigation/elements@^1.3.9": | |||
| version "1.3.9" | |||
| resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.9.tgz#33e26d7ad655b012e024ef0a005a3f66201287f8" | |||
| @@ -1974,6 +2014,11 @@ | |||
| resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" | |||
| integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== | |||
| "@types/qs@^6.5.3": | |||
| version "6.9.7" | |||
| resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" | |||
| integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== | |||
| "@types/react@*": | |||
| version "18.0.26" | |||
| resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.26.tgz#8ad59fc01fef8eaf5c74f4ea392621749f0b7917" | |||
| @@ -2355,7 +2400,7 @@ balanced-match@^1.0.0: | |||
| resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" | |||
| integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== | |||
| base64-js@^1.1.2, base64-js@^1.2.3, base64-js@^1.3.1, base64-js@^1.5.1: | |||
| base64-js@^1.1.2, base64-js@^1.2.3, base64-js@^1.3.0, base64-js@^1.3.1, base64-js@^1.5.1: | |||
| version "1.5.1" | |||
| resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" | |||
| integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== | |||
| @@ -2574,6 +2619,14 @@ cache-base@^1.0.1: | |||
| union-value "^1.0.0" | |||
| unset-value "^1.0.0" | |||
| call-bind@^1.0.0: | |||
| version "1.0.2" | |||
| resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" | |||
| integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== | |||
| dependencies: | |||
| function-bind "^1.1.1" | |||
| get-intrinsic "^1.0.2" | |||
| caller-callsite@^2.0.0: | |||
| version "2.0.0" | |||
| resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" | |||
| @@ -2693,6 +2746,15 @@ cliui@^6.0.0: | |||
| strip-ansi "^6.0.0" | |||
| wrap-ansi "^6.2.0" | |||
| cliui@^7.0.2: | |||
| version "7.0.4" | |||
| resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" | |||
| integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== | |||
| dependencies: | |||
| string-width "^4.2.0" | |||
| strip-ansi "^6.0.0" | |||
| wrap-ansi "^7.0.0" | |||
| clone-deep@^4.0.1: | |||
| version "4.0.1" | |||
| resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" | |||
| @@ -2744,7 +2806,7 @@ color-name@^1.0.0, color-name@~1.1.4: | |||
| resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" | |||
| integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== | |||
| color-string@^1.6.0, color-string@^1.9.0: | |||
| color-string@^1.5.3, color-string@^1.6.0, color-string@^1.9.0: | |||
| version "1.9.1" | |||
| resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" | |||
| integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== | |||
| @@ -2790,6 +2852,11 @@ commander@^4.0.0: | |||
| resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" | |||
| integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== | |||
| commander@^5.1.0: | |||
| version "5.1.0" | |||
| resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" | |||
| integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== | |||
| commander@^7.2.0: | |||
| version "7.2.0" | |||
| resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" | |||
| @@ -2810,6 +2877,13 @@ commondir@^1.0.1: | |||
| resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" | |||
| integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== | |||
| compare-urls@^2.0.0: | |||
| version "2.0.0" | |||
| resolved "https://registry.yarnpkg.com/compare-urls/-/compare-urls-2.0.0.tgz#9b378c4abd43980a8700fffec9afb85de4df9075" | |||
| integrity sha512-eCJcWn2OYFEIqbm70ta7LQowJOOZZqq1a2YbbFCFI1uwSvj+TWMwXVn7vPR1ceFNcAIt5RSTDbwdlX82gYLTkA== | |||
| dependencies: | |||
| normalize-url "^2.0.1" | |||
| compare-versions@^3.4.0: | |||
| version "3.6.0" | |||
| resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62" | |||
| @@ -3374,6 +3448,18 @@ expo-asset@~8.6.2: | |||
| path-browserify "^1.0.0" | |||
| url-parse "^1.5.9" | |||
| expo-auth-session@~3.7.3: | |||
| version "3.7.3" | |||
| resolved "https://registry.yarnpkg.com/expo-auth-session/-/expo-auth-session-3.7.3.tgz#ded1afbbf88e0c6e4098e59920b4f13927fc1f3d" | |||
| integrity sha512-0mX47j6WdpEoaFVxU36VBRkEjJKwAkqnRyNdd5g+Ab1fHXQJJK3nzjOjxuBzgE8mKSS9NGHr/At9IGY6MLrg2g== | |||
| dependencies: | |||
| expo-constants "~14.0.0" | |||
| expo-crypto "~12.0.0" | |||
| expo-linking "~3.2.0" | |||
| expo-web-browser "~12.0.0" | |||
| invariant "^2.2.4" | |||
| qs "6.9.1" | |||
| expo-constants@~14.0.0, expo-constants@~14.0.2: | |||
| version "14.0.2" | |||
| resolved "https://registry.yarnpkg.com/expo-constants/-/expo-constants-14.0.2.tgz#2cb1dec8f41a64c2fc5b4eecaf77d7661cad01cc" | |||
| @@ -3382,6 +3468,11 @@ expo-constants@~14.0.0, expo-constants@~14.0.2: | |||
| "@expo/config" "~7.0.2" | |||
| uuid "^3.3.2" | |||
| expo-crypto@~12.0.0: | |||
| version "12.0.0" | |||
| resolved "https://registry.yarnpkg.com/expo-crypto/-/expo-crypto-12.0.0.tgz#015e47fec27b07098fcef3676c6bf8b20767860a" | |||
| integrity sha512-2KC52eLYsXndDZOVFyr+K3Zs9wDgpqZ7F7fwAiUg+yNbE21CJrHKDFvo/Br0FAaDf/w9pUks5/qi1azB5sDzvg== | |||
| expo-error-recovery@~4.0.1: | |||
| version "4.0.1" | |||
| resolved "https://registry.yarnpkg.com/expo-error-recovery/-/expo-error-recovery-4.0.1.tgz#3e3333e134c992c234539d3773fe78915c883755" | |||
| @@ -3406,6 +3497,17 @@ expo-keep-awake@~11.0.1: | |||
| resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-11.0.1.tgz#ee354465892a94040ffe09901b85b469e7d54fb3" | |||
| integrity sha512-44ZjgLE4lnce2d40Pv8xsjMVc6R5GvgHOwZfkLYtGmgYG9TYrEJeEj5UfSeweXPL3pBFhXKfFU8xpGYMaHdP0A== | |||
| expo-linking@~3.2.0: | |||
| version "3.2.3" | |||
| resolved "https://registry.yarnpkg.com/expo-linking/-/expo-linking-3.2.3.tgz#7b493a7fea2aadafc88a42e2fc6a5a4ba6d47df9" | |||
| integrity sha512-PgiWCao9TecLOPdtWyiNSY+UQGAwdjFx4KbHd1YsF0KnM1CJ2idcaHpDRlQPWSNmDebUZYN461/dVtJi9b2krg== | |||
| dependencies: | |||
| "@types/qs" "^6.5.3" | |||
| expo-constants "~14.0.0" | |||
| invariant "^2.2.4" | |||
| qs "^6.9.1" | |||
| url-parse "^1.5.9" | |||
| expo-modules-autolinking@1.0.0: | |||
| version "1.0.0" | |||
| resolved "https://registry.yarnpkg.com/expo-modules-autolinking/-/expo-modules-autolinking-1.0.0.tgz#2daac20035e1ecf8e66d74dca9bd1b0d6c09166c" | |||
| @@ -3425,12 +3527,34 @@ expo-modules-core@1.0.3: | |||
| compare-versions "^3.4.0" | |||
| invariant "^2.2.4" | |||
| expo-random@~13.0.0: | |||
| version "13.0.0" | |||
| resolved "https://registry.yarnpkg.com/expo-random/-/expo-random-13.0.0.tgz#fc9c1496ac9f7555563d86de0db25966739c028f" | |||
| integrity sha512-aGb0vtUmFFuW0TF1rdOgsz89zEVD/RXUPUnnZy5+i3jJeQ2PerJ4uo72/EuWqHpCBNto8/qT+aCzFinmQDeTAA== | |||
| dependencies: | |||
| base64-js "^1.3.0" | |||
| expo-splash-screen@~0.17.5: | |||
| version "0.17.5" | |||
| resolved "https://registry.yarnpkg.com/expo-splash-screen/-/expo-splash-screen-0.17.5.tgz#a18dc59c1cc28ebbedbf0a7529a419d18ab0b311" | |||
| integrity sha512-ejSO78hwHXz8T9u8kh8t4r6CR4h70iBvA65gX8GK+dYxZl6/IANPbIb2VnUpND9vqfW+JnkDw+ZFst+gDnkpcQ== | |||
| dependencies: | |||
| "@expo/configure-splash-screen" "^0.6.0" | |||
| "@expo/prebuild-config" "5.0.7" | |||
| expo-status-bar@~1.4.2: | |||
| version "1.4.2" | |||
| resolved "https://registry.yarnpkg.com/expo-status-bar/-/expo-status-bar-1.4.2.tgz#14f2b9a6dc7d550578421f07e0046f5fafc2b403" | |||
| integrity sha512-ZWjO6D4ARGYfAd3SWDD3STNudHDhyBZDZjhhseqoEmsf7bS9ykny8KKOhlzJW24qIQNPhkgdvHhaw9fQwMJy3Q== | |||
| expo@^47.0.8: | |||
| expo-web-browser@~12.0.0: | |||
| version "12.0.0" | |||
| resolved "https://registry.yarnpkg.com/expo-web-browser/-/expo-web-browser-12.0.0.tgz#c8e117bfd6357df05ae3cf85acb423b44c4f6304" | |||
| integrity sha512-7/RUuE0sv5kf+mTw5/SOnks0Am1ctoxvT1Xi53Nom2EuXTKBV+b2Kf5xAw3ItoW5W4MHJUX3FdNI6qc9sS9+Pw== | |||
| dependencies: | |||
| compare-urls "^2.0.0" | |||
| expo@~47.0.8: | |||
| version "47.0.8" | |||
| resolved "https://registry.yarnpkg.com/expo/-/expo-47.0.8.tgz#80390fd63f8305103445069c647011915f7c32dd" | |||
| integrity sha512-PGNCIvrnYwHH4TDFsVocq/xhWZ5DW8N3bLkZJPZZgX6VgjtVLNsbZ+0lm1inLCZHP+6xSpSKRccjGHO/QQoMBQ== | |||
| @@ -3761,11 +3885,20 @@ gensync@^1.0.0-beta.2: | |||
| resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" | |||
| integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== | |||
| get-caller-file@^2.0.1: | |||
| get-caller-file@^2.0.1, get-caller-file@^2.0.5: | |||
| version "2.0.5" | |||
| resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" | |||
| integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== | |||
| get-intrinsic@^1.0.2: | |||
| version "1.1.3" | |||
| resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" | |||
| integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== | |||
| dependencies: | |||
| function-bind "^1.1.1" | |||
| has "^1.0.3" | |||
| has-symbols "^1.0.3" | |||
| get-port@^3.2.0: | |||
| version "3.2.0" | |||
| resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" | |||
| @@ -3874,6 +4007,11 @@ has-flag@^4.0.0: | |||
| resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" | |||
| integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== | |||
| has-symbols@^1.0.3: | |||
| version "1.0.3" | |||
| resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" | |||
| integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== | |||
| has-value@^0.3.1: | |||
| version "0.3.1" | |||
| resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" | |||
| @@ -4257,6 +4395,11 @@ is-path-inside@^3.0.2: | |||
| resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" | |||
| integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== | |||
| is-plain-obj@^1.0.0: | |||
| version "1.1.0" | |||
| resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" | |||
| integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== | |||
| is-plain-obj@^2.1.0: | |||
| version "2.1.0" | |||
| resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" | |||
| @@ -4614,7 +4757,7 @@ lodash.throttle@^4.1.1: | |||
| resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" | |||
| integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== | |||
| lodash@^4.17.13, lodash@^4.17.21, lodash@^4.17.4: | |||
| lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.21, lodash@^4.17.4: | |||
| version "4.17.21" | |||
| resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" | |||
| integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== | |||
| @@ -5284,6 +5427,15 @@ normalize-path@^3.0.0: | |||
| resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" | |||
| integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== | |||
| normalize-url@^2.0.1: | |||
| version "2.0.1" | |||
| resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" | |||
| integrity sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw== | |||
| dependencies: | |||
| prepend-http "^2.0.0" | |||
| query-string "^5.0.1" | |||
| sort-keys "^2.0.0" | |||
| npm-package-arg@^7.0.0: | |||
| version "7.0.0" | |||
| resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-7.0.0.tgz#52cdf08b491c0c59df687c4c925a89102ef794a5" | |||
| @@ -5332,6 +5484,11 @@ object-copy@^0.1.0: | |||
| define-property "^0.2.5" | |||
| kind-of "^3.0.3" | |||
| object-inspect@^1.9.0: | |||
| version "1.12.2" | |||
| resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" | |||
| integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== | |||
| object-visit@^1.0.0: | |||
| version "1.0.1" | |||
| resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" | |||
| @@ -5641,6 +5798,11 @@ pngjs@^3.3.0: | |||
| resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" | |||
| integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== | |||
| pngjs@^5.0.0: | |||
| version "5.0.0" | |||
| resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb" | |||
| integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw== | |||
| posix-character-classes@^0.1.0: | |||
| version "0.1.1" | |||
| resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" | |||
| @@ -5651,6 +5813,11 @@ postcss-value-parser@^4.2.0: | |||
| resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" | |||
| integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== | |||
| prepend-http@^2.0.0: | |||
| version "2.0.0" | |||
| resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" | |||
| integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== | |||
| pretty-bytes@5.6.0: | |||
| version "5.6.0" | |||
| resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" | |||
| @@ -5703,7 +5870,7 @@ prompts@^2.3.2, prompts@^2.4.0: | |||
| kleur "^3.0.3" | |||
| sisteransi "^1.0.5" | |||
| prop-types@^15.7.2: | |||
| prop-types@^15.5.10, prop-types@^15.7.2: | |||
| version "15.8.1" | |||
| resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" | |||
| integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== | |||
| @@ -5735,6 +5902,27 @@ qs@6.7.0: | |||
| resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" | |||
| integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== | |||
| qs@6.9.1: | |||
| version "6.9.1" | |||
| resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.1.tgz#20082c65cb78223635ab1a9eaca8875a29bf8ec9" | |||
| integrity sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA== | |||
| qs@^6.9.1: | |||
| version "6.11.0" | |||
| resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" | |||
| integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== | |||
| dependencies: | |||
| side-channel "^1.0.4" | |||
| query-string@^5.0.1: | |||
| version "5.1.1" | |||
| resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" | |||
| integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== | |||
| dependencies: | |||
| decode-uri-component "^0.2.0" | |||
| object-assign "^4.1.0" | |||
| strict-uri-encode "^1.0.0" | |||
| query-string@^7.0.0: | |||
| version "7.1.3" | |||
| resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328" | |||
| @@ -5842,11 +6030,23 @@ react-native-gradle-plugin@^0.70.3: | |||
| resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.70.3.tgz#cbcf0619cbfbddaa9128701aa2d7b4145f9c4fc8" | |||
| integrity sha512-oOanj84fJEXUg9FoEAQomA8ISG+DVIrTZ3qF7m69VQUJyOGYyDZmPqKcjvRku4KXlEH6hWO9i4ACLzNBh8gC0A== | |||
| react-native-indicators@^0.17.0: | |||
| version "0.17.0" | |||
| resolved "https://registry.yarnpkg.com/react-native-indicators/-/react-native-indicators-0.17.0.tgz#92f95efaf5fb53be576dfe4e1980a25655a93f55" | |||
| integrity sha512-s23em477GHGxWeGczWrixScAZD6tQU4mx1fttlrwhEGKOxhBgp55Kh3RoD9Wj4yna4e5W35xQNoPqoJAT6QW5A== | |||
| dependencies: | |||
| prop-types "^15.5.10" | |||
| react-native-iphone-x-helper@^1.3.0: | |||
| version "1.3.1" | |||
| resolved "https://registry.yarnpkg.com/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.3.1.tgz#20c603e9a0e765fd6f97396638bdeb0e5a60b010" | |||
| integrity sha512-HOf0jzRnq2/aFUcdCJ9w9JGzN3gdEg0zFE4FyYlp4jtidqU03D5X7ZegGKfT1EWteR0gPBGp9ye5T5FvSWi9Yg== | |||
| react-native-loading-spinner-overlay@^3.0.1: | |||
| version "3.0.1" | |||
| resolved "https://registry.yarnpkg.com/react-native-loading-spinner-overlay/-/react-native-loading-spinner-overlay-3.0.1.tgz#092481b8cce157d3af5ef942f845ad981f96bd36" | |||
| integrity sha512-4GdR54HQnKg2HPSSisVizfTLuyhSh4splY9eb8mKiYF1Ihjn/5EmdNo5bN3S7uKPFRC3WLzIZIouX6G6fXfnjw== | |||
| react-native-reanimated@~2.12.0: | |||
| version "2.12.0" | |||
| resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.12.0.tgz#5821eecfb1769b1617a67a2d4dec12fdeedb2b6e" | |||
| @@ -5895,6 +6095,14 @@ react-native-svg@13.4.0: | |||
| css-select "^5.1.0" | |||
| css-tree "^1.1.3" | |||
| react-native-vector-icons@^9.2.0: | |||
| version "9.2.0" | |||
| resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-9.2.0.tgz#3c0c82e95defd274d56363cbe8fead8d53167ebd" | |||
| integrity sha512-wKYLaFuQST/chH3AJRjmOLoLy3JEs1JR6zMNgTaemFpNoXs0ztRnTxcxFD9xhX7cJe1/zoN5BpQYe7kL0m5yyA== | |||
| dependencies: | |||
| prop-types "^15.7.2" | |||
| yargs "^16.1.1" | |||
| react-native-web@~0.18.7: | |||
| version "0.18.10" | |||
| resolved "https://registry.yarnpkg.com/react-native-web/-/react-native-web-0.18.10.tgz#fb4db047f4be7f9cf35f37ec8d52f7d1c450600f" | |||
| @@ -6274,7 +6482,7 @@ safe-regex@^1.1.0: | |||
| resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" | |||
| integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== | |||
| sax@>=0.6.0: | |||
| sax@>=0.6.0, sax@^1.2.4: | |||
| version "1.2.4" | |||
| resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" | |||
| integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== | |||
| @@ -6415,6 +6623,15 @@ shell-quote@^1.6.1, shell-quote@^1.7.3: | |||
| resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.4.tgz#33fe15dee71ab2a81fcbd3a52106c5cfb9fb75d8" | |||
| integrity sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw== | |||
| side-channel@^1.0.4: | |||
| version "1.0.4" | |||
| resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" | |||
| integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== | |||
| dependencies: | |||
| call-bind "^1.0.0" | |||
| get-intrinsic "^1.0.2" | |||
| object-inspect "^1.9.0" | |||
| signal-exit@^3.0.0, signal-exit@^3.0.2: | |||
| version "3.0.7" | |||
| resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" | |||
| @@ -6490,6 +6707,13 @@ snapdragon@^0.8.1: | |||
| source-map-resolve "^0.5.0" | |||
| use "^3.1.0" | |||
| sort-keys@^2.0.0: | |||
| version "2.0.0" | |||
| resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" | |||
| integrity sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg== | |||
| dependencies: | |||
| is-plain-obj "^1.0.0" | |||
| source-map-resolve@^0.5.0: | |||
| version "0.5.3" | |||
| resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" | |||
| @@ -6600,6 +6824,11 @@ stream-buffers@2.2.x: | |||
| resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-2.2.0.tgz#91d5f5130d1cef96dcfa7f726945188741d09ee4" | |||
| integrity sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg== | |||
| strict-uri-encode@^1.0.0: | |||
| version "1.1.0" | |||
| resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" | |||
| integrity sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== | |||
| strict-uri-encode@^2.0.0: | |||
| version "2.0.0" | |||
| resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" | |||
| @@ -7260,7 +7489,7 @@ ws@^7, ws@^7.5.1: | |||
| resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" | |||
| integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== | |||
| xcode@^3.0.1: | |||
| xcode@^3.0.0, xcode@^3.0.1: | |||
| version "3.0.1" | |||
| resolved "https://registry.yarnpkg.com/xcode/-/xcode-3.0.1.tgz#3efb62aac641ab2c702458f9a0302696146aa53c" | |||
| integrity sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA== | |||
| @@ -7268,6 +7497,13 @@ xcode@^3.0.1: | |||
| simple-plist "^1.1.0" | |||
| uuid "^7.0.3" | |||
| xml-js@^1.6.11: | |||
| version "1.6.11" | |||
| resolved "https://registry.yarnpkg.com/xml-js/-/xml-js-1.6.11.tgz#927d2f6947f7f1c19a316dd8eea3614e8b18f8e9" | |||
| integrity sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g== | |||
| dependencies: | |||
| sax "^1.2.4" | |||
| xml2js@0.4.23: | |||
| version "0.4.23" | |||
| resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" | |||
| @@ -7301,6 +7537,11 @@ y18n@^4.0.0: | |||
| resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" | |||
| integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== | |||
| y18n@^5.0.5: | |||
| version "5.0.8" | |||
| resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" | |||
| integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== | |||
| yallist@^4.0.0: | |||
| version "4.0.0" | |||
| resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" | |||
| @@ -7319,6 +7560,11 @@ yargs-parser@^18.1.2: | |||
| camelcase "^5.0.0" | |||
| decamelize "^1.2.0" | |||
| yargs-parser@^20.2.2: | |||
| version "20.2.9" | |||
| resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" | |||
| integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== | |||
| yargs@^15.1.0, yargs@^15.3.1: | |||
| version "15.4.1" | |||
| resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" | |||
| @@ -7336,6 +7582,19 @@ yargs@^15.1.0, yargs@^15.3.1: | |||
| y18n "^4.0.0" | |||
| yargs-parser "^18.1.2" | |||
| yargs@^16.1.1: | |||
| version "16.2.0" | |||
| resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" | |||
| integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== | |||
| dependencies: | |||
| cliui "^7.0.2" | |||
| escalade "^3.1.1" | |||
| get-caller-file "^2.0.5" | |||
| require-directory "^2.1.1" | |||
| string-width "^4.2.0" | |||
| y18n "^5.0.5" | |||
| yargs-parser "^20.2.2" | |||
| yocto-queue@^0.1.0: | |||
| version "0.1.0" | |||
| resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" | |||