Apple sign in is mostly working. Did some other stuff too
This commit is contained in:
parent
708c0553f5
commit
84cae666bf
5
.gitignore
vendored
5
.gitignore
vendored
@ -29,6 +29,11 @@ yarn-error.*
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# builds
|
||||
*.ipa
|
||||
ios/
|
||||
android/
|
||||
|
||||
# Apple Secret
|
||||
AuthKey_*.p8
|
||||
|
||||
|
46
app.json
46
app.json
@ -1,24 +1,41 @@
|
||||
{
|
||||
"expo": {
|
||||
"name": "Tech Tracker Expo",
|
||||
"slug": "tech-tracker-expo",
|
||||
"name": "Tech Tracker",
|
||||
"slug": "tech-tracker",
|
||||
"version": "1.0.0",
|
||||
"orientation": "portrait",
|
||||
"icon": "./assets/images/icon.png",
|
||||
"scheme": "com.techtracker",
|
||||
"userInterfaceStyle": "automatic",
|
||||
"splash": {
|
||||
"image": "./assets/images/splash.png",
|
||||
"resizeMode": "contain",
|
||||
"backgroundColor": "#2e2f3d"
|
||||
},
|
||||
"newArchEnabled": true,
|
||||
"ios": {
|
||||
"usesAppleSignIn": true,
|
||||
"supportsTablet": true,
|
||||
"bundleIdentifier": "com.gibbyb.techtrackerexpo"
|
||||
"bundleIdentifier": "com.gbrown.techtracker",
|
||||
"config": {
|
||||
"usesNonExemptEncryption": false
|
||||
},
|
||||
"infoPlist": {
|
||||
"ITSAppUsesNonExemptEncryption": false,
|
||||
"NSLocationWhenInUseUsageDescription": "This app uses your location in order to allow you to share your location in chat.",
|
||||
"NSCameraUsageDescription": "This app uses your camera to take photos & send them in the chat."
|
||||
}
|
||||
},
|
||||
"android": {
|
||||
"adaptiveIcon": {
|
||||
"foregroundImage": "./assets/images/adaptive-icon.png",
|
||||
"backgroundColor": "#ffffff"
|
||||
"backgroundColor": "#2e2f3d"
|
||||
},
|
||||
"package": "com.gibbyb.techtrackerexpo"
|
||||
"permissions": [
|
||||
"android.permission.ACCESS_COARSE_LOCATION",
|
||||
"android.permission.ACCESS_FINE_LOCATION"
|
||||
],
|
||||
"package": "com.gbrown.techtracker"
|
||||
},
|
||||
"web": {
|
||||
"bundler": "metro",
|
||||
@ -36,8 +53,19 @@
|
||||
"backgroundColor": "#ffffff"
|
||||
}
|
||||
],
|
||||
"expo-secure-store",
|
||||
"expo-apple-authentication"
|
||||
[
|
||||
"expo-secure-store",
|
||||
{
|
||||
"faceIDPermission": "Allow $(PRODUCT_NAME) to access your FaceID biometric data."
|
||||
}
|
||||
],
|
||||
"expo-apple-authentication",
|
||||
[
|
||||
"expo-location",
|
||||
{
|
||||
"locationAlwaysAndWhenInUsePermission": "Allow $(PRODUCT_NAME) to use your location."
|
||||
}
|
||||
]
|
||||
],
|
||||
"experiments": {
|
||||
"typedRoutes": true
|
||||
@ -51,8 +79,6 @@
|
||||
"updates": {
|
||||
"url": "https://u.expo.dev/7d872415-9160-4e06-ba95-4c3442e04b79"
|
||||
},
|
||||
"runtimeVersion": {
|
||||
"policy": "appVersion"
|
||||
}
|
||||
"runtimeVersion": "1.0.0"
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ import { ThemedView } from '@/components/theme';
|
||||
import { Session } from '@supabase/supabase-js';
|
||||
import { useColorScheme } from '@/hooks/useColorScheme';
|
||||
import { supabase } from '@/lib/supabase';
|
||||
import LoginPage from '@/components/auth/Login';
|
||||
import Account from '@/components/Account';
|
||||
import Auth from '@/components/auth/Auth';
|
||||
import PushNotificationManager from '@/services/PushNotificationManager';
|
||||
|
||||
// Prevent the splash screen from auto-hiding before asset loading is complete.
|
||||
SplashScreen.preventAutoHideAsync();
|
||||
@ -44,19 +44,21 @@ const RootLayout = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider value={scheme === 'dark' ? DarkTheme : DefaultTheme}>
|
||||
{session && session.user ? (
|
||||
<Stack>
|
||||
<Stack.Screen name='(tabs)' options={{ headerShown: false }} />
|
||||
<Stack.Screen name='+not-found' />
|
||||
</Stack>
|
||||
) : (
|
||||
<ThemedView style={{ flex: 1 }}>
|
||||
<LoginPage />
|
||||
</ThemedView>
|
||||
)}
|
||||
<StatusBar style='auto' />
|
||||
</ThemeProvider>
|
||||
<PushNotificationManager>
|
||||
<ThemeProvider value={scheme === 'dark' ? DarkTheme : DefaultTheme}>
|
||||
{session && session.user ? (
|
||||
<Stack>
|
||||
<Stack.Screen name='(tabs)' options={{ headerShown: false }} />
|
||||
<Stack.Screen name='+not-found' />
|
||||
</Stack>
|
||||
) : (
|
||||
<ThemedView style={{ flex: 1 }}>
|
||||
<Auth />
|
||||
</ThemedView>
|
||||
)}
|
||||
<StatusBar style='auto' />
|
||||
</ThemeProvider>
|
||||
</PushNotificationManager>
|
||||
);
|
||||
};
|
||||
|
||||
|
99
components/auth/AppleSignIn.native.tsx
Normal file
99
components/auth/AppleSignIn.native.tsx
Normal file
@ -0,0 +1,99 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { supabase } from '@/lib/supabase';
|
||||
import * as AppleAuthentication from 'expo-apple-authentication'
|
||||
import { useColorScheme } from '@/hooks/useColorScheme';
|
||||
import { ThemedView } from '@/components/theme';
|
||||
import { StyleSheet, Platform } from 'react-native';
|
||||
import Constants from 'expo-constants';
|
||||
import * as Notifications from 'expo-notifications';
|
||||
|
||||
const AppleSignInButton = () => {
|
||||
const scheme = useColorScheme() ?? 'dark';
|
||||
|
||||
const signInWithApple = async () => {
|
||||
try {
|
||||
const credential = await AppleAuthentication.signInAsync({
|
||||
requestedScopes: [
|
||||
AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
|
||||
AppleAuthentication.AppleAuthenticationScope.EMAIL,
|
||||
],
|
||||
});
|
||||
//const projectId = Constants.expoConfig?.extra?.projectId;
|
||||
//if (!projectId) throw new Error('No projectId found in expo.config.json');
|
||||
//const pushToken = await Notifications.getExpoPushTokenAsync({
|
||||
//projectId,
|
||||
//});
|
||||
if (credential.identityToken) {
|
||||
const full_name = (
|
||||
credential.fullName &&
|
||||
credential.fullName.givenName &&
|
||||
credential.fullName.familyName
|
||||
)
|
||||
? `${credential.fullName.givenName} ${credential.fullName.familyName}`
|
||||
: null;
|
||||
|
||||
const {
|
||||
error,
|
||||
data: { user, session },
|
||||
} = await supabase.auth.signInWithIdToken({
|
||||
provider: 'apple',
|
||||
token: credential.identityToken,
|
||||
});
|
||||
console.log(JSON.stringify({ error, user }, null, 2))
|
||||
if (!error) {
|
||||
if (user) {
|
||||
const data: any = {
|
||||
full_name,
|
||||
};
|
||||
const { error: updateError } = await supabase.auth.updateUser({
|
||||
data,
|
||||
});
|
||||
if (updateError) {
|
||||
console.error('Error updating user metadata:', updateError);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new Error('No identityToken.')
|
||||
}
|
||||
} catch (e: any) {
|
||||
if (e.code === 'ERR_REQUEST_CANCELED') {
|
||||
// handle that the user canceled the sign-in flow
|
||||
console.log('User canceled sign-in flow');
|
||||
} else {
|
||||
// handle other errors
|
||||
console.log('Error signing in with Apple:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Platform.OS !== 'ios') return <div/>;
|
||||
else return (
|
||||
|
||||
<ThemedView style={[styles.verticallySpaced, styles.mt20]}>
|
||||
<AppleAuthentication.AppleAuthenticationButton
|
||||
buttonType={AppleAuthentication.AppleAuthenticationButtonType.SIGN_IN}
|
||||
buttonStyle={
|
||||
scheme === 'light'
|
||||
? AppleAuthentication.AppleAuthenticationButtonStyle.BLACK
|
||||
: AppleAuthentication.AppleAuthenticationButtonStyle.WHITE
|
||||
}
|
||||
cornerRadius={5}
|
||||
style={{ width: 200, height: 64 }}
|
||||
onPress={signInWithApple}
|
||||
/>
|
||||
</ThemedView>
|
||||
);
|
||||
}
|
||||
export default AppleSignInButton;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
verticallySpaced: {
|
||||
paddingTop: 4,
|
||||
paddingBottom: 4,
|
||||
alignItems: 'center',
|
||||
},
|
||||
mt20: {
|
||||
marginTop: 20,
|
||||
},
|
||||
});
|
@ -1,128 +0,0 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { StyleSheet, Alert, Platform } from 'react-native';
|
||||
import * as AppleAuthentication from 'expo-apple-authentication';
|
||||
import { supabase } from '@/lib/supabase';
|
||||
import { useColorScheme } from '@/hooks/useColorScheme';
|
||||
|
||||
type AppleSignInProps = {
|
||||
onSignInStart?: () => void;
|
||||
onSignInComplete?: () => void;
|
||||
onSignInError?: (error: any) => void;
|
||||
};
|
||||
|
||||
const AppleSignIn: React.FC<AppleSignInProps> = ({
|
||||
onSignInStart,
|
||||
onSignInComplete,
|
||||
onSignInError,
|
||||
}) => {
|
||||
const scheme = useColorScheme() ?? 'dark';
|
||||
const [isAppleAuthAvailable, setIsAppleAuthAvailable] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (Platform.OS === 'ios') {
|
||||
AppleAuthentication.isAvailableAsync().then(setIsAppleAuthAvailable);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleAppleSignIn = async () => {
|
||||
try {
|
||||
onSignInStart?.();
|
||||
|
||||
// Get credentials from Apple
|
||||
const credential = await AppleAuthentication.signInAsync({
|
||||
requestedScopes: [
|
||||
AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
|
||||
AppleAuthentication.AppleAuthenticationScope.EMAIL,
|
||||
],
|
||||
});
|
||||
|
||||
if (!credential.email) {
|
||||
throw new Error('Email is required for Apple Sign In');
|
||||
}
|
||||
|
||||
// Extract user information
|
||||
const { email, fullName, user: appleUserId } = credential;
|
||||
|
||||
// Create a name from the fullName object if available
|
||||
let name = null;
|
||||
if (fullName?.givenName || fullName?.familyName) {
|
||||
name = `${fullName?.givenName || ''} ${fullName?.familyName || ''}`.trim();
|
||||
}
|
||||
|
||||
// Create a deterministic password based on the Apple user ID
|
||||
// This way the user can sign in again with the same password
|
||||
const password = `Apple-${appleUserId.substring(0, 16)}`;
|
||||
|
||||
// First try to sign in (in case the user already exists)
|
||||
const { data: signInData, error: signInError } = await supabase.auth.signInWithPassword({
|
||||
email,
|
||||
password,
|
||||
});
|
||||
|
||||
if (!signInError && signInData?.user) {
|
||||
// User exists and signed in successfully
|
||||
onSignInComplete?.();
|
||||
return;
|
||||
}
|
||||
|
||||
// If sign-in failed, create a new user
|
||||
const { data: signUpData, error: signUpError } = await supabase.auth.signUp({
|
||||
email,
|
||||
password,
|
||||
options: {
|
||||
data: {
|
||||
full_name: name,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (signUpError) {
|
||||
throw signUpError;
|
||||
}
|
||||
|
||||
// User created successfully
|
||||
onSignInComplete?.();
|
||||
} catch (error) {
|
||||
console.error('Apple sign in error:', error);
|
||||
|
||||
if (error.code === 'ERR_REQUEST_CANCELED') {
|
||||
console.log('Sign in was canceled');
|
||||
} else {
|
||||
Alert.alert(
|
||||
'Sign in error',
|
||||
'An error occurred while signing in with Apple. Please try again.',
|
||||
);
|
||||
onSignInError?.(error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Only render on iOS and if Apple Authentication is available
|
||||
if (Platform.OS !== 'ios' || !isAppleAuthAvailable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<AppleAuthentication.AppleAuthenticationButton
|
||||
buttonType={AppleAuthentication.AppleAuthenticationButtonType.SIGN_IN}
|
||||
buttonStyle={
|
||||
scheme === 'light'
|
||||
? AppleAuthentication.AppleAuthenticationButtonStyle.BLACK
|
||||
: AppleAuthentication.AppleAuthenticationButtonStyle.WHITE
|
||||
}
|
||||
cornerRadius={10}
|
||||
style={styles.button}
|
||||
onPress={handleAppleSignIn}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
button: {
|
||||
width: 320,
|
||||
height: 50,
|
||||
marginVertical: 10,
|
||||
},
|
||||
});
|
||||
|
||||
export default AppleSignIn;
|
@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
|
||||
import { Alert, StyleSheet, AppState, Image, Platform } from 'react-native';
|
||||
import { supabase } from '@/lib/supabase';
|
||||
import { ThemedView, ThemedText, ThemedTextButton, ThemedTextInput } from '@/components/theme';
|
||||
import AppleSignIn from '@/components/auth/AppleSignIn';
|
||||
import AppleSignInButton from '@/components/auth/AppleSignIn.native';
|
||||
|
||||
// Tells Supabase Auth to continuously refresh the session automatically if
|
||||
// the app is in the foreground. When this is added, you will continue to receive
|
||||
@ -18,7 +18,7 @@ if (Platform.OS !== 'web') {
|
||||
});
|
||||
}
|
||||
|
||||
const LoginPage = () => {
|
||||
const Auth = () => {
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
@ -102,20 +102,12 @@ const LoginPage = () => {
|
||||
fontSize={24}
|
||||
/>
|
||||
</ThemedView>
|
||||
|
||||
{/* Apple Sign In - Only shows on iOS */}
|
||||
<ThemedView style={[styles.verticallySpaced, styles.mt20]}>
|
||||
<AppleSignIn
|
||||
onSignInStart={() => setLoading(true)}
|
||||
onSignInComplete={() => setLoading(false)}
|
||||
onSignInError={() => setLoading(false)}
|
||||
/>
|
||||
</ThemedView>
|
||||
<AppleSignInButton />
|
||||
</ThemedView>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoginPage;
|
||||
export default Auth;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
6
constants/Types.ts
Normal file
6
constants/Types.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export type NotificationMessage = {
|
||||
sound?: string;
|
||||
title: string;
|
||||
body: string;
|
||||
data?: any;
|
||||
};
|
676
package-lock.json
generated
676
package-lock.json
generated
@ -10,6 +10,7 @@
|
||||
"license": "0BSD",
|
||||
"dependencies": {
|
||||
"@expo/metro-runtime": "~4.0.1",
|
||||
"@expo/ngrok": "4.1.0",
|
||||
"@expo/vector-icons": "^14.0.2",
|
||||
"@react-native-async-storage/async-storage": "^1.23.1",
|
||||
"@react-navigation/bottom-tabs": "^7.2.0",
|
||||
@ -19,12 +20,15 @@
|
||||
"expo": "~52.0.28",
|
||||
"expo-apple-authentication": "~7.1.3",
|
||||
"expo-blur": "~14.0.3",
|
||||
"expo-constants": "~17.0.5",
|
||||
"expo-dev-client": "~5.0.10",
|
||||
"expo-constants": "~17.0.7",
|
||||
"expo-dev-client": "~5.0.12",
|
||||
"expo-device": "~7.0.2",
|
||||
"expo-font": "~13.0.3",
|
||||
"expo-haptics": "~14.0.1",
|
||||
"expo-insights": "~0.8.2",
|
||||
"expo-linking": "~7.0.5",
|
||||
"expo-location": "~18.0.7",
|
||||
"expo-notifications": "~0.29.13",
|
||||
"expo-router": "~4.0.17",
|
||||
"expo-secure-store": "~14.0.1",
|
||||
"expo-splash-screen": "~0.29.21",
|
||||
@ -2697,6 +2701,184 @@
|
||||
"react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@expo/ngrok": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@expo/ngrok/-/ngrok-4.1.0.tgz",
|
||||
"integrity": "sha512-PrtWxBt/SnOF1jZkf7oWznhEPFrmYKKeJPLVRKnEBd/y4eUYfoiNIXOzflIzhdrMubjWVI+pFuPJ6nkjVL95/Q==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@expo/ngrok-bin": "2.3.40",
|
||||
"got": "^11.5.1",
|
||||
"uuid": "^3.3.2",
|
||||
"yaml": "^1.10.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@expo/ngrok-bin": {
|
||||
"version": "2.3.40",
|
||||
"resolved": "https://registry.npmjs.org/@expo/ngrok-bin/-/ngrok-bin-2.3.40.tgz",
|
||||
"integrity": "sha512-40GK1CY1QLPDHSQS7Fd36CJeZgMwtbeezkgp4tzfExVRVtWw30jOBCsM7TBB9IqEmmX7C/XwG47scMQHCnMw8A==",
|
||||
"bin": {
|
||||
"ngrok": "bin/ngrok.js"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@expo/ngrok-bin-darwin-arm64": "2.3.40",
|
||||
"@expo/ngrok-bin-darwin-x64": "2.3.40",
|
||||
"@expo/ngrok-bin-freebsd-ia32": "2.3.40",
|
||||
"@expo/ngrok-bin-freebsd-x64": "2.3.40",
|
||||
"@expo/ngrok-bin-linux-arm": "2.3.40",
|
||||
"@expo/ngrok-bin-linux-arm64": "2.3.40",
|
||||
"@expo/ngrok-bin-linux-ia32": "2.3.40",
|
||||
"@expo/ngrok-bin-linux-x64": "2.3.40",
|
||||
"@expo/ngrok-bin-sunos-x64": "2.3.40",
|
||||
"@expo/ngrok-bin-win32-ia32": "2.3.40",
|
||||
"@expo/ngrok-bin-win32-x64": "2.3.40"
|
||||
}
|
||||
},
|
||||
"node_modules/@expo/ngrok-bin-darwin-arm64": {
|
||||
"version": "2.3.40",
|
||||
"resolved": "https://registry.npmjs.org/@expo/ngrok-bin-darwin-arm64/-/ngrok-bin-darwin-arm64-2.3.40.tgz",
|
||||
"integrity": "sha512-Zij81v/bIsVBvgXgYS71xbi/3lqKfVEfr7rId8BsHO3Ec1nQcp/I+729W3KX9PUHzWlXCLxOKZ3uF4jL/TcNbg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@expo/ngrok-bin-darwin-x64": {
|
||||
"version": "2.3.40",
|
||||
"resolved": "https://registry.npmjs.org/@expo/ngrok-bin-darwin-x64/-/ngrok-bin-darwin-x64-2.3.40.tgz",
|
||||
"integrity": "sha512-nqGLfxIjZBoT79VDk5mqaHQKCWkunSi486zGLeB8Ye8Qar1yo4STFwks+DqTbnGD5ItArQz2LzKRVE4YXuJFuw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@expo/ngrok-bin-freebsd-ia32": {
|
||||
"version": "2.3.40",
|
||||
"resolved": "https://registry.npmjs.org/@expo/ngrok-bin-freebsd-ia32/-/ngrok-bin-freebsd-ia32-2.3.40.tgz",
|
||||
"integrity": "sha512-Ji3jZaOuIZO+ege23kZZAAEPUYkF+6mCpghb16b28Is1QHOSl2L4foDnAcWyzSEiBihMicxWltaQyaaxA0fdgw==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@expo/ngrok-bin-freebsd-x64": {
|
||||
"version": "2.3.40",
|
||||
"resolved": "https://registry.npmjs.org/@expo/ngrok-bin-freebsd-x64/-/ngrok-bin-freebsd-x64-2.3.40.tgz",
|
||||
"integrity": "sha512-mVnzKGQmOyXimZx6udoiyo3ZTYLZnPShlTySaDP0tqQ0vYz4ZscgvaYpMmDSPrsP/YG2owmKgzmOE2V+ycD8qA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@expo/ngrok-bin-linux-arm": {
|
||||
"version": "2.3.40",
|
||||
"resolved": "https://registry.npmjs.org/@expo/ngrok-bin-linux-arm/-/ngrok-bin-linux-arm-2.3.40.tgz",
|
||||
"integrity": "sha512-Je1QBd7x0hbZa4T3gZbVgD0cSzstpJ7Mu0+dM2lOB+vm3bd603yHtD0RlLdqARJFhPTE1M2zLd68gCEeZ5fRgQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@expo/ngrok-bin-linux-arm64": {
|
||||
"version": "2.3.40",
|
||||
"resolved": "https://registry.npmjs.org/@expo/ngrok-bin-linux-arm64/-/ngrok-bin-linux-arm64-2.3.40.tgz",
|
||||
"integrity": "sha512-S6kbnRqsVXHo/bWNxc0jfq33aQQRsGWjb6e7SvZ2DgXsPFLn27cfK0eHD96uCssARDVhzPsc+VU/B3d8C1DT5A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@expo/ngrok-bin-linux-ia32": {
|
||||
"version": "2.3.40",
|
||||
"resolved": "https://registry.npmjs.org/@expo/ngrok-bin-linux-ia32/-/ngrok-bin-linux-ia32-2.3.40.tgz",
|
||||
"integrity": "sha512-gPY5zv5Fu+TkCm5iZolXQbu7e5hc7fTllIKn/zJQxxZs/WCvSxyB5ip6vQcHiavu/kjr0HtNciPX/guXvWENkg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@expo/ngrok-bin-linux-x64": {
|
||||
"version": "2.3.40",
|
||||
"resolved": "https://registry.npmjs.org/@expo/ngrok-bin-linux-x64/-/ngrok-bin-linux-x64-2.3.40.tgz",
|
||||
"integrity": "sha512-yOuwpOmMe6RGnk9ninlM7Zg1EiF81ptFOcFmT61PDOA4gK8/ttZKTMkDQiq0DZdcXUyE0HCr83EglJZTnHIzPA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@expo/ngrok-bin-sunos-x64": {
|
||||
"version": "2.3.40",
|
||||
"resolved": "https://registry.npmjs.org/@expo/ngrok-bin-sunos-x64/-/ngrok-bin-sunos-x64-2.3.40.tgz",
|
||||
"integrity": "sha512-0itEIQ7KsxRbF9nJk6tt0Ey+9TDC5H7krOsy3t7DPx01EvtaiEdMyhmE1XWjBtwr8+BaY9CpEhUWkx4iCcE4cw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
]
|
||||
},
|
||||
"node_modules/@expo/ngrok-bin-win32-ia32": {
|
||||
"version": "2.3.40",
|
||||
"resolved": "https://registry.npmjs.org/@expo/ngrok-bin-win32-ia32/-/ngrok-bin-win32-ia32-2.3.40.tgz",
|
||||
"integrity": "sha512-RAunwOAskfU0R5mYlxxB+bihLJ4nLRx5/x+q5nIq1muYmaqLvGtkQQHZKzgHJANJ7ZIbzfJY57IN2UICpibgIQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@expo/ngrok-bin-win32-x64": {
|
||||
"version": "2.3.40",
|
||||
"resolved": "https://registry.npmjs.org/@expo/ngrok-bin-win32-x64/-/ngrok-bin-win32-x64-2.3.40.tgz",
|
||||
"integrity": "sha512-a8xtUxX/Ftp2ho+/+VR5GCg0ttP9MNzYj58TVjfiKMkl4mVrbFVIzEinRzmy7PhiOWxqGQSCOdzEfa6C2G4nEA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@expo/ngrok/node_modules/uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"uuid": "bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/@expo/osascript": {
|
||||
"version": "2.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.1.6.tgz",
|
||||
@ -2920,6 +3102,12 @@
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@ide/backoff": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@ide/backoff/-/backoff-1.0.0.tgz",
|
||||
"integrity": "sha512-F0YfUDjvT+Mtt/R4xdl2X0EYCHMMiJqNLdxHD++jDT5ydEFIyqbCHh51Qx2E211dgZprPKhV7sHmnXKpLuvc5g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@isaacs/cliui": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||
@ -4357,6 +4545,18 @@
|
||||
"integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@sindresorhus/is": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
|
||||
"integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/is?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@sinonjs/commons": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
|
||||
@ -4449,6 +4649,18 @@
|
||||
"@supabase/storage-js": "2.7.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@szmarczak/http-timer": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
|
||||
"integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"defer-to-connect": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tootallnate/once": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
|
||||
@ -4500,6 +4712,18 @@
|
||||
"@babel/types": "^7.20.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/cacheable-request": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz",
|
||||
"integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/http-cache-semantics": "*",
|
||||
"@types/keyv": "^3.1.4",
|
||||
"@types/node": "*",
|
||||
"@types/responselike": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/cookie": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
|
||||
@ -4553,6 +4777,12 @@
|
||||
"integrity": "sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/http-cache-semantics": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz",
|
||||
"integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/istanbul-lib-coverage": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
|
||||
@ -4606,6 +4836,15 @@
|
||||
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/keyv": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
|
||||
"integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.13.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.9.tgz",
|
||||
@ -4658,6 +4897,15 @@
|
||||
"@types/react": "^18"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/responselike": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz",
|
||||
"integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/stack-utils": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
|
||||
@ -4672,9 +4920,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "8.5.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.14.tgz",
|
||||
"integrity": "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw==",
|
||||
"version": "8.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.0.tgz",
|
||||
"integrity": "sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
@ -4967,9 +5215,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.14.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
||||
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
|
||||
"version": "8.14.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
|
||||
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
@ -5204,6 +5452,19 @@
|
||||
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/assert": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz",
|
||||
"integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2",
|
||||
"is-nan": "^1.3.2",
|
||||
"object-is": "^1.1.5",
|
||||
"object.assign": "^4.1.4",
|
||||
"util": "^0.12.5"
|
||||
}
|
||||
},
|
||||
"node_modules/ast-types": {
|
||||
"version": "0.15.2",
|
||||
"resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz",
|
||||
@ -5478,6 +5739,12 @@
|
||||
"@babel/core": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/badgin": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/badgin/-/badgin-1.2.3.tgz",
|
||||
"integrity": "sha512-NQGA7LcfCpSzIbGRbkgjgdWkjy7HI+Th5VLxTJfW5EeaAf3fnS+xWQaQOCYiny+q6QSvxqoSO04vCx+4u++EJw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
@ -5722,6 +5989,48 @@
|
||||
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/cacheable-lookup": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
|
||||
"integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cacheable-request": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz",
|
||||
"integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"clone-response": "^1.0.2",
|
||||
"get-stream": "^5.1.0",
|
||||
"http-cache-semantics": "^4.0.0",
|
||||
"keyv": "^4.0.0",
|
||||
"lowercase-keys": "^2.0.0",
|
||||
"normalize-url": "^6.0.1",
|
||||
"responselike": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/cacheable-request/node_modules/get-stream": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
|
||||
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"pump": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
|
||||
@ -6070,6 +6379,18 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/clone-response": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz",
|
||||
"integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mimic-response": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/co": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||
@ -6516,6 +6837,33 @@
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/decompress-response": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
|
||||
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mimic-response": "^3.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/decompress-response/node_modules/mimic-response": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
|
||||
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/dedent": {
|
||||
"version": "1.5.3",
|
||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz",
|
||||
@ -6574,6 +6922,15 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/defer-to-connect": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
|
||||
"integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/define-data-property": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
||||
@ -6600,6 +6957,23 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/define-properties": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
|
||||
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"define-data-property": "^1.0.1",
|
||||
"has-property-descriptors": "^1.0.0",
|
||||
"object-keys": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/del": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz",
|
||||
@ -7268,6 +7642,15 @@
|
||||
"react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-application": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/expo-application/-/expo-application-6.0.2.tgz",
|
||||
"integrity": "sha512-qcj6kGq3mc7x5yIb5KxESurFTJCoEKwNEL34RdPEvTB/xhl7SeVZlu05sZBqxB1V4Ryzq/LsCb7NHNfBbb3L7A==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"expo": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-asset": {
|
||||
"version": "11.0.4",
|
||||
"resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-11.0.4.tgz",
|
||||
@ -7362,6 +7745,44 @@
|
||||
"expo": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-device": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/expo-device/-/expo-device-7.0.2.tgz",
|
||||
"integrity": "sha512-0PkTixE4Qi8VQBjixnj4aw2f6vE4tUZH7GK8zHROGKlBypZKcWmsA+W/Vp3RC5AyREjX71pO/hjKTSo/vF0E2w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ua-parser-js": "^0.7.33"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"expo": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-device/node_modules/ua-parser-js": {
|
||||
"version": "0.7.40",
|
||||
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.40.tgz",
|
||||
"integrity": "sha512-us1E3K+3jJppDBa3Tl0L3MOJiGhe1C6P0+nIvQAFYbxlMAx0h81eOwLmU57xgqToduDDPx3y5QsdjPfDu+FgOQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/ua-parser-js"
|
||||
},
|
||||
{
|
||||
"type": "paypal",
|
||||
"url": "https://paypal.me/faisalman"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/faisalman"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"ua-parser-js": "script/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-eas-client": {
|
||||
"version": "0.13.3",
|
||||
"resolved": "https://registry.npmjs.org/expo-eas-client/-/expo-eas-client-0.13.3.tgz",
|
||||
@ -7445,6 +7866,15 @@
|
||||
"react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-location": {
|
||||
"version": "18.0.7",
|
||||
"resolved": "https://registry.npmjs.org/expo-location/-/expo-location-18.0.7.tgz",
|
||||
"integrity": "sha512-EPN5yTtDCH3EMiJpJFCWuD+vJkhVbl1j3tMYo3wkhGJN7xlvZf6naLXj8vYntdXSa5M40KjOgjaRiUUqf6+dXw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"expo": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-manifests": {
|
||||
"version": "0.15.7",
|
||||
"resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-0.15.7.tgz",
|
||||
@ -7522,6 +7952,26 @@
|
||||
"invariant": "^2.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-notifications": {
|
||||
"version": "0.29.13",
|
||||
"resolved": "https://registry.npmjs.org/expo-notifications/-/expo-notifications-0.29.13.tgz",
|
||||
"integrity": "sha512-GHye6XeI1uEeVttJO/hGwUyA5cgQsxR3mi5q37yOE7cZN3cMj36pIfEEmjXEr0nWIWSzoJ0w8c2QxNj5xfP1pA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@expo/image-utils": "^0.6.4",
|
||||
"@ide/backoff": "^1.0.0",
|
||||
"abort-controller": "^3.0.0",
|
||||
"assert": "^2.0.0",
|
||||
"badgin": "^1.1.5",
|
||||
"expo-application": "~6.0.2",
|
||||
"expo-constants": "~17.0.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"expo": "*",
|
||||
"react": "*",
|
||||
"react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-router": {
|
||||
"version": "4.0.17",
|
||||
"resolved": "https://registry.npmjs.org/expo-router/-/expo-router-4.0.17.tgz",
|
||||
@ -7984,9 +8434,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/flow-parser": {
|
||||
"version": "0.262.0",
|
||||
"resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.262.0.tgz",
|
||||
"integrity": "sha512-K3asSw4s2/sRoUC4xD2OfGi04gdYCCFRgkcwEXi5JyfFhS0HrFWLcDPp55ttv95OY5970WKl4T+7hWrnuOAUMQ==",
|
||||
"version": "0.263.0",
|
||||
"resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.263.0.tgz",
|
||||
"integrity": "sha512-F0Tr7SUvZ4BQYglFOkr8rCTO5FPjCwMhm/6i57h40F80Oz/hzzkqte4lGO0vGJ7THQonuXcTyYqCdKkAwt5d2w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
@ -8316,6 +8766,31 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/got": {
|
||||
"version": "11.8.6",
|
||||
"resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz",
|
||||
"integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sindresorhus/is": "^4.0.0",
|
||||
"@szmarczak/http-timer": "^4.0.5",
|
||||
"@types/cacheable-request": "^6.0.1",
|
||||
"@types/responselike": "^1.0.0",
|
||||
"cacheable-lookup": "^5.0.3",
|
||||
"cacheable-request": "^7.0.2",
|
||||
"decompress-response": "^6.0.0",
|
||||
"http2-wrapper": "^1.0.0-beta.5.2",
|
||||
"lowercase-keys": "^2.0.0",
|
||||
"p-cancelable": "^2.0.0",
|
||||
"responselike": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.19.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/got?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
@ -8450,6 +8925,12 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/http-cache-semantics": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
|
||||
"integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/http-errors": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||
@ -8490,6 +8971,19 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/http2-wrapper": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz",
|
||||
"integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"quick-lru": "^5.1.1",
|
||||
"resolve-alpn": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/https-proxy-agent": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
@ -8846,6 +9340,22 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-nan": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz",
|
||||
"integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.0",
|
||||
"define-properties": "^1.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
@ -10227,6 +10737,12 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/json-buffer": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
|
||||
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-parse-better-errors": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
|
||||
@ -10322,6 +10838,15 @@
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/keyv": {
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"json-buffer": "3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/kind-of": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
|
||||
@ -10789,6 +11314,15 @@
|
||||
"loose-envify": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/lowercase-keys": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
|
||||
"integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
@ -11368,6 +11902,15 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/mimic-response": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
|
||||
"integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
@ -11653,6 +12196,18 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-url": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
|
||||
"integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-package-arg": {
|
||||
"version": "11.0.3",
|
||||
"resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.3.tgz",
|
||||
@ -11735,6 +12290,51 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/object-is": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
|
||||
"integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
"define-properties": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/object-keys": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/object.assign": {
|
||||
"version": "4.1.7",
|
||||
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
|
||||
"integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.8",
|
||||
"call-bound": "^1.0.3",
|
||||
"define-properties": "^1.2.1",
|
||||
"es-object-atoms": "^1.0.0",
|
||||
"has-symbols": "^1.1.0",
|
||||
"object-keys": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/on-finished": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
||||
@ -11911,6 +12511,15 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/p-cancelable": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz",
|
||||
"integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/p-finally": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
|
||||
@ -12518,6 +13127,18 @@
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/quick-lru": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
|
||||
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
@ -13199,6 +13820,12 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve-alpn": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
|
||||
"integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/resolve-cwd": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
|
||||
@ -13236,6 +13863,18 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/responselike": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz",
|
||||
"integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lowercase-keys": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/restore-cursor": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
|
||||
@ -14468,9 +15107,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/terser-webpack-plugin": {
|
||||
"version": "5.3.12",
|
||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.12.tgz",
|
||||
"integrity": "sha512-jDLYqo7oF8tJIttjXO6jBY5Hk8p3A8W4ttih7cCEq64fQFWmgJ4VqAQjKr7WwIDlmXKEc6QeoRb5ecjZ+2afcg==",
|
||||
"version": "5.3.13",
|
||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.13.tgz",
|
||||
"integrity": "sha512-JG3pBixF6kx2o0Yfz2K6pqh72DpwTI08nooHd06tcj5WyIt5SsSiUYqRT+kemrGUNSuSzVhwfZ28aO8gogajNQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
@ -15486,6 +16125,15 @@
|
||||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
"version": "1.10.2",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
|
||||
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
"version": "17.7.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
|
||||
|
14
package.json
14
package.json
@ -6,8 +6,8 @@
|
||||
"scripts": {
|
||||
"start": "expo start",
|
||||
"reset-project": "node ./scripts/reset-project.js",
|
||||
"android": "expo start --android",
|
||||
"ios": "expo start --ios",
|
||||
"android": "expo run:android",
|
||||
"ios": "expo run:ios",
|
||||
"web": "expo start --web",
|
||||
"test": "jest --watchAll",
|
||||
"lint": "expo lint",
|
||||
@ -28,8 +28,8 @@
|
||||
"expo": "~52.0.28",
|
||||
"expo-apple-authentication": "~7.1.3",
|
||||
"expo-blur": "~14.0.3",
|
||||
"expo-constants": "~17.0.5",
|
||||
"expo-dev-client": "~5.0.10",
|
||||
"expo-constants": "~17.0.7",
|
||||
"expo-dev-client": "~5.0.12",
|
||||
"expo-font": "~13.0.3",
|
||||
"expo-haptics": "~14.0.1",
|
||||
"expo-insights": "~0.8.2",
|
||||
@ -52,7 +52,11 @@
|
||||
"react-native-safe-area-context": "4.12.0",
|
||||
"react-native-screens": "~4.4.0",
|
||||
"react-native-web": "~0.19.13",
|
||||
"react-native-webview": "13.12.5"
|
||||
"react-native-webview": "13.12.5",
|
||||
"@expo/ngrok": "4.1.0",
|
||||
"expo-notifications": "~0.29.13",
|
||||
"expo-device": "~7.0.2",
|
||||
"expo-location": "~18.0.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
|
112
services/PushNotificationManager.tsx
Normal file
112
services/PushNotificationManager.tsx
Normal file
@ -0,0 +1,112 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { Alert, Platform } from 'react-native';
|
||||
import * as Device from 'expo-device';
|
||||
import * as Notifications from 'expo-notifications';
|
||||
import Constants from 'expo-constants';
|
||||
import { NotificationMessage } from '@/constants/Types';
|
||||
|
||||
Notifications.setNotificationHandler({
|
||||
handleNotification: async () => ({
|
||||
shouldShowAlert: true,
|
||||
shouldPlaySound: false,
|
||||
shouldSetBadge: false,
|
||||
}),
|
||||
});
|
||||
|
||||
export const sendPushNotification = async(expoPushToken: string | null, notification: NotificationMessage) => {
|
||||
if (!expoPushToken) {
|
||||
Alert.alert('Error', 'No push token found.');
|
||||
return;
|
||||
}
|
||||
const message = {
|
||||
to: expoPushToken,
|
||||
sound: notification.sound ?? 'default',
|
||||
title: notification.title,
|
||||
body: notification.body,
|
||||
data: notification.data ?? {},
|
||||
};
|
||||
try {
|
||||
const response = await fetch('https://exp.host/--/api/v2/push/send', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Accept-encoding': 'gzip, deflate',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(message),
|
||||
});
|
||||
const result = await response.json();
|
||||
} catch (error) {
|
||||
console.error('Error sending push notification:', error);
|
||||
Alert.alert('Error', 'Failed to send push notification.');
|
||||
}
|
||||
};
|
||||
|
||||
const handleRegistrationError = (errorMessage: string) => {
|
||||
alert(errorMessage);
|
||||
throw new Error(errorMessage);
|
||||
};
|
||||
|
||||
async function registerForPushNotificationsAsync() {
|
||||
let token;
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
await Notifications.setNotificationChannelAsync('default', {
|
||||
name: 'default',
|
||||
importance: Notifications.AndroidImportance.MAX,
|
||||
vibrationPattern: [0, 250, 250, 250],
|
||||
lightColor: '#FF231F7C',
|
||||
});
|
||||
}
|
||||
|
||||
if (Device.isDevice) {
|
||||
const { status: existingStatus } = await Notifications.getPermissionsAsync();
|
||||
let finalStatus = existingStatus;
|
||||
if (existingStatus !== 'granted') {
|
||||
const { status } = await Notifications.requestPermissionsAsync();
|
||||
finalStatus = status;
|
||||
}
|
||||
if (finalStatus !== 'granted') {
|
||||
alert('Failed to get push token for push notification!');
|
||||
return;
|
||||
}
|
||||
const projectId = Constants.expoConfig?.extra?.eas?.projectId;
|
||||
if (!projectId) {
|
||||
alert('Project ID not found');
|
||||
return;
|
||||
}
|
||||
token = (await Notifications.getExpoPushTokenAsync({ projectId })).data;
|
||||
} else {
|
||||
alert('Must use physical device for Push Notifications');
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
const PushNotificationManager = ({ children }: { children: React.ReactNode }) => {
|
||||
const [expoPushToken, setExpoPushToken] = useState<string | undefined>('');
|
||||
const [notification, setNotification] = useState<Notifications.Notification | undefined>(undefined);
|
||||
const notificationListener = useRef<Notifications.Subscription>();
|
||||
const responseListener = useRef<Notifications.Subscription>();
|
||||
|
||||
useEffect(() => {
|
||||
registerForPushNotificationsAsync().then(token => setExpoPushToken(token));
|
||||
|
||||
notificationListener.current = Notifications.addNotificationReceivedListener(notification => {
|
||||
setNotification(notification);
|
||||
});
|
||||
|
||||
responseListener.current = Notifications.addNotificationResponseReceivedListener(response => {
|
||||
console.log(response);
|
||||
// Handle notification response here
|
||||
});
|
||||
|
||||
return () => {
|
||||
Notifications.removeNotificationSubscription(notificationListener.current!);
|
||||
Notifications.removeNotificationSubscription(responseListener.current!);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return <>{children}</>;
|
||||
}
|
||||
export default PushNotificationManager;
|
Loading…
x
Reference in New Issue
Block a user