trying to get push notifications to work

This commit is contained in:
Gabriel Brown 2024-09-25 11:40:11 -05:00
parent 868ad01c3f
commit bebdbbad39
15 changed files with 20429 additions and 176 deletions

View File

@ -26,6 +26,7 @@
<category android:name="android.intent.category.BROWSABLE"/> <category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="myapp"/> <data android:scheme="myapp"/>
<data android:scheme="com.gibbyb.fuse"/> <data android:scheme="com.gibbyb.fuse"/>
<data android:scheme="exp+fuse"/>
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:exported="false"/> <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:exported="false"/>

0
android/gradlew vendored Normal file → Executable file
View File

View File

@ -1,10 +1,11 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { StyleSheet, ActivityIndicator, TouchableOpacity } from 'react-native'; import { StyleSheet, ActivityIndicator, TouchableOpacity, View } from 'react-native';
import { ThemedText } from '@/components/ThemedText'; import { ThemedText } from '@/components/ThemedText';
import { ThemedView } from '@/components/ThemedView'; import { ThemedView } from '@/components/ThemedView';
import { SafeAreaView } from 'react-native-safe-area-context'; // Import for safe area handling
import { LinearGradient } from 'expo-linear-gradient'; import { LinearGradient } from 'expo-linear-gradient';
import axios from 'axios'; import axios from 'axios';
import ChangeDateDrawer from '@/components/ChangeDateDrawer'; import ChangeDateDrawer from '@/components/ChangeDateDrawer'; // Date drawer component
const API_KEY = process.env.EXPO_PUBLIC_API_KEY; const API_KEY = process.env.EXPO_PUBLIC_API_KEY;
const BASE_URL = process.env.EXPO_PUBLIC_BASE_URL; const BASE_URL = process.env.EXPO_PUBLIC_BASE_URL;
@ -16,7 +17,6 @@ const fetchCountdownDate = async () => {
params: { apiKey: API_KEY } params: { apiKey: API_KEY }
}); });
if (response.data && response.data[0] && response.data[0].countdown) { if (response.data && response.data[0] && response.data[0].countdown) {
//console.log('Countdown date:', response.data[0].countdown);
return new Date(response.data[0].countdown); return new Date(response.data[0].countdown);
} else { } else {
console.error('Unexpected API response format:', response.data); console.error('Unexpected API response format:', response.data);
@ -98,29 +98,32 @@ export default function TabTwoScreen() {
start={{ x: 0, y: 0 }} start={{ x: 0, y: 0 }}
end={{ x: 1, y: 1 }} end={{ x: 1, y: 1 }}
> >
<ThemedView style={styles.container}> <SafeAreaView style={styles.safeContainer}>
<ThemedText style={styles.title}>Countdown to Next Visit</ThemedText> <ThemedView style={styles.innerContainer}>
<ThemedView style={styles.countdownContainer}> <ThemedText style={styles.title}>Countdown to Next Visit</ThemedText>
<CountdownItem value={countdown.days} label={days} /> <ThemedView style={styles.countdownContainer}>
<CountdownItem value={countdown.hours} label={hours} /> {/* Countdown items displayed horizontally with flexbox */}
<CountdownItem value={countdown.minutes} label={minutes} /> <CountdownItem value={countdown.days} label={days} />
<CountdownItem value={countdown.seconds} label={seconds} /> <CountdownItem value={countdown.hours} label={hours} />
<CountdownItem value={countdown.minutes} label={minutes} />
<CountdownItem value={countdown.seconds} label={seconds} />
</ThemedView>
<TouchableOpacity
style={styles.changeButton}
onPress={() => setIsDateDrawerVisible(true)}
>
<ThemedText style={styles.changeButtonText}>Change Date</ThemedText>
</TouchableOpacity>
{targetDate && (
<ChangeDateDrawer
isVisible={isDateDrawerVisible}
onClose={() => setIsDateDrawerVisible(false)}
onDateChange={handleDateChange}
currentDate={targetDate}
/>
)}
</ThemedView> </ThemedView>
<TouchableOpacity </SafeAreaView>
style={styles.changeButton}
onPress={() => setIsDateDrawerVisible(true)}
>
<ThemedText style={styles.changeButtonText}>Change Date</ThemedText>
</TouchableOpacity>
{targetDate && (
<ChangeDateDrawer
isVisible={isDateDrawerVisible}
onClose={() => setIsDateDrawerVisible(false)}
onDateChange={handleDateChange}
currentDate={targetDate}
/>
)}
</ThemedView>
</LinearGradient> </LinearGradient>
); );
} }
@ -135,31 +138,39 @@ function CountdownItem({ value, label }: { value: number; label: string }) {
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
safeContainer: {
flex: 1,
backgroundColor: 'transparent', // Background color for safety area view
},
container: { container: {
flex: 1, flex: 1,
backgroundColor: 'transparent',
},
innerContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
paddingHorizontal: 20, // Padding around the edges
backgroundColor: 'transparent', backgroundColor: 'transparent',
}, },
title: { title: {
fontSize: 64, fontSize: 40, // Shrinking the title for smaller screens
lineHeight: 64, lineHeight: 50,
fontWeight: 'bold', fontWeight: '600',
marginTop: 100,
marginBottom: 60,
textAlign: 'center', textAlign: 'center',
paddingHorizontal: 20, paddingHorizontal: 10,
}, },
countdownContainer: { countdownContainer: {
flexDirection: 'row', flexDirection: 'row',
justifyContent: 'center', justifyContent: 'space-around', // Spread countdown items more evenly
alignItems: 'center', alignItems: 'center',
width: '100%',
backgroundColor: 'transparent', backgroundColor: 'transparent',
marginBottom: 180, marginVertical: 40, // Added some space between countdown and title/button
}, },
countdownItem: { countdownItem: {
margin: 10,
lineHeight: 42,
alignItems: 'center', alignItems: 'center',
marginHorizontal: 10, // Each item has horizontal spacing
backgroundColor: 'transparent', backgroundColor: 'transparent',
}, },
countdownValue: { countdownValue: {
@ -168,18 +179,18 @@ const styles = StyleSheet.create({
fontWeight: 'bold', fontWeight: 'bold',
}, },
countdownLabel: { countdownLabel: {
fontSize: 32, fontSize: 18, // Reducing size of the label for better fit
lineHeight: 42, lineHeight: 24,
}, },
changeButton: { changeButton: {
backgroundColor: '#730FF8', backgroundColor: '#730FF8',
padding: 15, padding: 12,
borderRadius: 10, borderRadius: 8,
marginTop: 40, marginTop: 20,
}, },
changeButtonText: { changeButtonText: {
color: 'white', color: 'white',
fontSize: 22, fontSize: 18,
fontWeight: 'bold', fontWeight: 'bold',
}, },
}); });

View File

@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { StyleSheet } from 'react-native'; import { StyleSheet, SafeAreaView } from 'react-native';
import { ThemedText } from '@/components/ThemedText'; import { ThemedText } from '@/components/ThemedText';
import { ThemedView } from '@/components/ThemedView'; import { ThemedView } from '@/components/ThemedView';
import { LinearGradient } from 'expo-linear-gradient'; import { LinearGradient } from 'expo-linear-gradient';
@ -50,9 +50,11 @@ export default function HomeScreen() {
start={{ x: 0, y: 0 }} start={{ x: 0, y: 0 }}
end={{ x: 1, y: 1 }} end={{ x: 1, y: 1 }}
> >
<ThemedView style={styles.container}> <SafeAreaView style={styles.container}>
<ThemedText style={styles.title}>{message}</ThemedText> <ThemedView style={styles.container}>
</ThemedView> <ThemedText style={styles.title}>{message}</ThemedText>
</ThemedView>
</SafeAreaView>
</LinearGradient> </LinearGradient>
); );
} }

View File

@ -7,44 +7,49 @@ import {
Keyboard, Keyboard,
TouchableWithoutFeedback, TouchableWithoutFeedback,
KeyboardAvoidingView, KeyboardAvoidingView,
Platform, Platform,
View SafeAreaView, // SafeAreaView import for handling safe areas
View
} from 'react-native'; } from 'react-native';
import { ThemedText } from '@/components/ThemedText'; import { ThemedText } from '@/components/ThemedText';
import { ThemedView } from '@/components/ThemedView';
import { LinearGradient } from 'expo-linear-gradient'; import { LinearGradient } from 'expo-linear-gradient';
import AsyncStorage from '@react-native-async-storage/async-storage'; import AsyncStorage from '@react-native-async-storage/async-storage';
import axios from 'axios'; import axios from 'axios';
// Environment variables
const API_KEY = process.env.EXPO_PUBLIC_API_KEY; const API_KEY = process.env.EXPO_PUBLIC_API_KEY;
const BASE_URL = process.env.EXPO_PUBLIC_BASE_URL; const BASE_URL = process.env.EXPO_PUBLIC_BASE_URL;
export default function SendMessageScreen() { export default function SendMessageScreen() {
const [message, setMessage] = useState(''); const [message, setMessage] = useState('');
const [userId, setUserId] = useState(null); const [userId, setUserId] = useState<number | null>(null); // Use number type for userId
const [inputHeight, setInputHeight] = useState(100); const [inputHeight, setInputHeight] = useState(120); // Set initial height for TextInput
// Update TextInput height dynamically
const updateInputHeight = (height: number) => { const updateInputHeight = (height: number) => {
setInputHeight(Math.max(100, height)); setInputHeight(Math.max(120, height)); // Ensure it doesn't shrink below 120px
}; };
// On component mount, get the user ID from AsyncStorage
useEffect(() => { useEffect(() => {
const getUserId = async () => {
try {
const storedUser = await AsyncStorage.getItem('@user');
if (storedUser) {
const user = JSON.parse(storedUser);
setUserId(user.id);
}
} catch (error) {
console.error('Failed to get user ID:', error);
}
};
getUserId(); getUserId();
}, []); }, []);
const getUserId = async () => { // Function to send a message
try {
const storedUser = await AsyncStorage.getItem('@user');
if (storedUser) {
const user = JSON.parse(storedUser);
setUserId(user.id);
}
} catch (error) {
console.error('Failed to get user ID:', error);
}
};
const sendMessage = async () => { const sendMessage = async () => {
// Input validation
if (!message.trim()) { if (!message.trim()) {
Alert.alert('Error', 'Please enter a message'); Alert.alert('Error', 'Please enter a message');
return; return;
@ -60,8 +65,8 @@ export default function SendMessageScreen() {
params: { apiKey: API_KEY, userId, message } params: { apiKey: API_KEY, userId, message }
}); });
Alert.alert('Success', 'Message sent successfully'); Alert.alert('Success', 'Message sent successfully');
setMessage(''); setMessage(''); // Clear the message input on success
Keyboard.dismiss(); Keyboard.dismiss(); // Dismiss the keyboard
} catch (error) { } catch (error) {
console.error('Failed to send message:', error); console.error('Failed to send message:', error);
Alert.alert('Error', 'Failed to send message. Please try again.'); Alert.alert('Error', 'Failed to send message. Please try again.');
@ -69,75 +74,87 @@ export default function SendMessageScreen() {
}; };
return ( return (
// Ensure keyboard behaves correctly on both iOS and Android
<KeyboardAvoidingView <KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : "height"} behavior={Platform.OS === "ios" ? "padding" : "height"}
style={{flex: 1}} style={{ flex: 1 }}
> >
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}> <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<LinearGradient {/* SafeAreaView for notch and layout safety */}
colors={['#F67C0A', '#F60AD3']} <SafeAreaView style={styles.safeContainer}>
style={styles.container} <LinearGradient
start={{ x: 0, y: 0 }} colors={['#F67C0A', '#F60AD3']}
end={{ x: 1, y: 1 }} style={styles.container}
> start={{ x: 0, y: 0 }}
<View style={styles.container}> end={{ x: 1, y: 1 }}
<TextInput >
style={[styles.input, { height: inputHeight }]} <View style={styles.chatContainer}>
value={message} <TextInput
onChangeText={setMessage} style={[styles.input, { height: inputHeight }]} // Dynamic height
placeholder="Send a message" value={message}
placeholderTextColor="#FFFFFF" onChangeText={setMessage}
multiline placeholder="Write a message"
numberOfLines={4} placeholderTextColor="#FFFFFF"
textAlignVertical="top" multiline // Allows multiple lines
onContentSizeChange={(event) => numberOfLines={4}
updateInputHeight(event.nativeEvent.contentSize.height) textAlignVertical="top" // Align text at the top
} onContentSizeChange={(event) =>
/> updateInputHeight(event.nativeEvent.contentSize.height)
<TouchableOpacity style={styles.button} onPress={sendMessage}> }
<ThemedText style={styles.buttonText}>Send Message</ThemedText> />
</TouchableOpacity>
</View> {/* Send Message Button */}
</LinearGradient> <TouchableOpacity style={styles.button} onPress={sendMessage}>
<ThemedText style={styles.buttonText}>Send Message</ThemedText>
</TouchableOpacity>
</View>
</LinearGradient>
</SafeAreaView>
</TouchableWithoutFeedback> </TouchableWithoutFeedback>
</KeyboardAvoidingView> </KeyboardAvoidingView>
); );
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
safeContainer: {
flex: 1,
backgroundColor: 'transparent', // Ensure full-screen safe area
},
container: { container: {
flex: 1, flex: 1,
alignItems: 'center',
padding: 20,
backgroundColor: 'transparent', backgroundColor: 'transparent',
width: '100%', },
chatContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: 20, // Ensures padding around the input and button
}, },
input: { input: {
width: '100%', width: '100%',
minHeight: 120, minHeight: 150, // Minimum height for the TextInput
borderColor: 'transparent', borderColor: 'transparent',
borderWidth: 1, borderWidth: 1,
borderRadius: 10, borderRadius: 10,
padding: 10, padding: 10,
marginBottom: 20, marginBottom: 10,
marginTop: 160, fontSize: 32, // Adjust font size to shrink for smaller devices
fontSize: 42, lineHeight: 40, // Adjust line height for better readability
lineHeight: 60,
textAlign: 'center', textAlign: 'center',
color: '#FFFFFF', color: '#FFFFFF',
fontWeight: 'bold', fontWeight: 'bold',
backgroundColor: 'transparent', //backgroundColor: 'rgba(0, 0, 0, 0.1)', // Subtle background for text input
backgroundColor: 'transparent', // Transparent background
}, },
button: { button: {
backgroundColor: '#730FF8', backgroundColor: '#730FF8',
padding: 15, paddingVertical: 12,
borderColor: '#730FF8', paddingHorizontal: 20,
borderRadius: 10, borderRadius: 10,
}, },
buttonText: { buttonText: {
color: 'white', color: 'white',
fontSize: 22, fontSize: 18,
fontWeight: 'bold', fontWeight: 'bold',
}, },
}); });

View File

@ -62,14 +62,11 @@ export default function RootLayout() {
}, [loaded]); }, [loaded]);
const handleUserSelected = async (selectedUser: User) => { const handleUserSelected = async (selectedUser: User) => {
setUser(selectedUser); console.log('User selected:', selectedUser); // Debug log
try { try {
await AsyncStorage.setItem('@user', JSON.stringify(selectedUser)); await AsyncStorage.setItem('@user', JSON.stringify(selectedUser));
console.log('User data stored in AsyncStorage:', selectedUser); // Debug log
// Store the Push Token to your server when the user is selected (optional) setUser(selectedUser);
if (expoPushToken) {
await savePushToken(selectedUser.id, expoPushToken); // Hypothetical function to send token to server
}
} catch (e) { } catch (e) {
console.error('Failed to save user or push token', e); console.error('Failed to save user or push token', e);
} }
@ -89,35 +86,37 @@ export default function RootLayout() {
useEffect(() => { useEffect(() => {
// Register for push notifications and set the push token // Register for push notifications and set the push token
registerForPushNotificationsAsync().then(async (token) => { registerForPushNotificationsAsync().then(async (token) => {
if (token) { const storedUser = await AsyncStorage.getItem('@user');
setExpoPushToken(token); if (!storedUser) {
console.log('No user found in AsyncStorage'); // Debug log
return;
}
try {
const storedUser = await AsyncStorage.getItem('@user');
console.log('Stored user data:', storedUser); // Debug log
// Upload push token to backend when successfully received if (storedUser) {
try { const user = JSON.parse(storedUser);
const storedUser = await AsyncStorage.getItem('@user'); console.log('Parsed user data:', user); // Debug log
if (storedUser) {
const user = JSON.parse(storedUser);
// Send the push token to your Next.js API, along with the user's ID // Send the push token to your Next.js API
await fetch(`${BASE_URL}/api/updatePushToken`, { await fetch(`${BASE_URL}/updatePushToken`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify({ body: JSON.stringify({
apiKey: API_KEY, // Use the API key stored in the environment apiKey: API_KEY,
userId: user.id, // The logged-in user's ID userId: user.id,
pushToken: token, // The Expo push token collected pushToken: token,
}), }),
}); });
console.log('Push token update request sent with user ID:', user.id); // Debug log
console.log('Push token successfully sent to backend'); } else {
} else { console.log('No user found in AsyncStorage');
console.log('No user found in AsyncStorage');
}
} catch (error) {
console.error('Failed to send push token to backend', error);
} }
} catch (error) {
console.error('Failed to send push token to backend', error);
} }
}); });
@ -215,10 +214,3 @@ async function registerForPushNotificationsAsync() {
return token; return token;
} }
// (Optional) A function to store push tokens in your backend server
async function savePushToken(userId: number, expoPushToken: string) {
// You would need to implement this function to save the user's push token to your backend.
// For example, you could send a POST request to your Next.js API that stores expoPushToken
console.log('Saving push token for user:', userId, 'with token:', expoPushToken);
}

BIN
build-1726251745948.ipa Normal file

Binary file not shown.

View File

@ -1,11 +1,15 @@
PODS: PODS:
- boost (1.83.0) - boost (1.83.0)
- DoubleConversion (1.1.6) - DoubleConversion (1.1.6)
- EXApplication (5.9.1):
- ExpoModulesCore
- EXConstants (16.0.2): - EXConstants (16.0.2):
- ExpoModulesCore - ExpoModulesCore
- EXJSONUtils (0.13.1) - EXJSONUtils (0.13.1)
- EXManifests (0.14.3): - EXManifests (0.14.3):
- ExpoModulesCore - ExpoModulesCore
- EXNotifications (0.28.16):
- ExpoModulesCore
- Expo (51.0.32): - Expo (51.0.32):
- ExpoModulesCore - ExpoModulesCore
- expo-dev-client (4.0.26): - expo-dev-client (4.0.26):
@ -217,6 +221,8 @@ PODS:
- Yoga - Yoga
- ExpoAsset (10.0.10): - ExpoAsset (10.0.10):
- ExpoModulesCore - ExpoModulesCore
- ExpoDevice (6.0.2):
- ExpoModulesCore
- ExpoFileSystem (17.0.1): - ExpoFileSystem (17.0.1):
- ExpoModulesCore - ExpoModulesCore
- ExpoFont (12.0.10): - ExpoFont (12.0.10):
@ -1538,15 +1544,18 @@ PODS:
DEPENDENCIES: DEPENDENCIES:
- boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`)
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- EXApplication (from `../node_modules/expo-application/ios`)
- EXConstants (from `../node_modules/expo-constants/ios`) - EXConstants (from `../node_modules/expo-constants/ios`)
- EXJSONUtils (from `../node_modules/expo-json-utils/ios`) - EXJSONUtils (from `../node_modules/expo-json-utils/ios`)
- EXManifests (from `../node_modules/expo-manifests/ios`) - EXManifests (from `../node_modules/expo-manifests/ios`)
- EXNotifications (from `../node_modules/expo-notifications/ios`)
- Expo (from `../node_modules/expo`) - Expo (from `../node_modules/expo`)
- expo-dev-client (from `../node_modules/expo-dev-client/ios`) - expo-dev-client (from `../node_modules/expo-dev-client/ios`)
- expo-dev-launcher (from `../node_modules/expo-dev-launcher`) - expo-dev-launcher (from `../node_modules/expo-dev-launcher`)
- expo-dev-menu (from `../node_modules/expo-dev-menu`) - expo-dev-menu (from `../node_modules/expo-dev-menu`)
- expo-dev-menu-interface (from `../node_modules/expo-dev-menu-interface/ios`) - expo-dev-menu-interface (from `../node_modules/expo-dev-menu-interface/ios`)
- ExpoAsset (from `../node_modules/expo-asset/ios`) - ExpoAsset (from `../node_modules/expo-asset/ios`)
- ExpoDevice (from `../node_modules/expo-device/ios`)
- ExpoFileSystem (from `../node_modules/expo-file-system/ios`) - ExpoFileSystem (from `../node_modules/expo-file-system/ios`)
- ExpoFont (from `../node_modules/expo-font/ios`) - ExpoFont (from `../node_modules/expo-font/ios`)
- ExpoHead (from `../node_modules/expo-router/ios`) - ExpoHead (from `../node_modules/expo-router/ios`)
@ -1628,12 +1637,16 @@ EXTERNAL SOURCES:
:podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec"
DoubleConversion: DoubleConversion:
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
EXApplication:
:path: "../node_modules/expo-application/ios"
EXConstants: EXConstants:
:path: "../node_modules/expo-constants/ios" :path: "../node_modules/expo-constants/ios"
EXJSONUtils: EXJSONUtils:
:path: "../node_modules/expo-json-utils/ios" :path: "../node_modules/expo-json-utils/ios"
EXManifests: EXManifests:
:path: "../node_modules/expo-manifests/ios" :path: "../node_modules/expo-manifests/ios"
EXNotifications:
:path: "../node_modules/expo-notifications/ios"
Expo: Expo:
:path: "../node_modules/expo" :path: "../node_modules/expo"
expo-dev-client: expo-dev-client:
@ -1646,6 +1659,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/expo-dev-menu-interface/ios" :path: "../node_modules/expo-dev-menu-interface/ios"
ExpoAsset: ExpoAsset:
:path: "../node_modules/expo-asset/ios" :path: "../node_modules/expo-asset/ios"
ExpoDevice:
:path: "../node_modules/expo-device/ios"
ExpoFileSystem: ExpoFileSystem:
:path: "../node_modules/expo-file-system/ios" :path: "../node_modules/expo-file-system/ios"
ExpoFont: ExpoFont:
@ -1789,15 +1804,18 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS: SPEC CHECKSUMS:
boost: d3f49c53809116a5d38da093a8aa78bf551aed09 boost: d3f49c53809116a5d38da093a8aa78bf551aed09
DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5 DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5
EXApplication: c08200c34daca7af7fd76ac4b9d606077410e8ad
EXConstants: 409690fbfd5afea964e5e9d6c4eb2c2b59222c59 EXConstants: 409690fbfd5afea964e5e9d6c4eb2c2b59222c59
EXJSONUtils: 30c17fd9cc364d722c0946a550dfbf1be92ef6a4 EXJSONUtils: 30c17fd9cc364d722c0946a550dfbf1be92ef6a4
EXManifests: c1fab4c3237675e7b0299ea8df0bcb14baca4f42 EXManifests: c1fab4c3237675e7b0299ea8df0bcb14baca4f42
EXNotifications: b1b174716b287e161350a18de1d253aabceeea2d
Expo: 33132a667698a3259a4e6c0af1b4936388e5fa33 Expo: 33132a667698a3259a4e6c0af1b4936388e5fa33
expo-dev-client: 4f9100af6be210a360aa67f42649881251aa362a expo-dev-client: 4f9100af6be210a360aa67f42649881251aa362a
expo-dev-launcher: c8e85bf244a2492448c88adbc3585ca13572f7b9 expo-dev-launcher: c8e85bf244a2492448c88adbc3585ca13572f7b9
expo-dev-menu: 0db38ce92be7228dadb588f7069e037fd9d165d8 expo-dev-menu: 0db38ce92be7228dadb588f7069e037fd9d165d8
expo-dev-menu-interface: be32c09f1e03833050f0ee290dcc86b3ad0e73e4 expo-dev-menu-interface: be32c09f1e03833050f0ee290dcc86b3ad0e73e4
ExpoAsset: 323700f291684f110fb55f0d4022a3362ea9f875 ExpoAsset: 323700f291684f110fb55f0d4022a3362ea9f875
ExpoDevice: fc94f0e42ecdfd897e7590f2874fc64dfa7e9b1c
ExpoFileSystem: 80bfe850b1f9922c16905822ecbf97acd711dc51 ExpoFileSystem: 80bfe850b1f9922c16905822ecbf97acd711dc51
ExpoFont: 00756e6c796d8f7ee8d211e29c8b619e75cbf238 ExpoFont: 00756e6c796d8f7ee8d211e29c8b619e75cbf238
ExpoHead: fcb28a68ed4ba28f177394d2dfb8a0a8824cd103 ExpoHead: fcb28a68ed4ba28f177394d2dfb8a0a8824cd103

View File

@ -3,7 +3,7 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 46; objectVersion = 54;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
@ -30,7 +30,7 @@
6C2E3173556A471DD304B334 /* Pods-fuse.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fuse.debug.xcconfig"; path = "Target Support Files/Pods-fuse/Pods-fuse.debug.xcconfig"; sourceTree = "<group>"; }; 6C2E3173556A471DD304B334 /* Pods-fuse.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fuse.debug.xcconfig"; path = "Target Support Files/Pods-fuse/Pods-fuse.debug.xcconfig"; sourceTree = "<group>"; };
7A4D352CD337FB3A3BF06240 /* Pods-fuse.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fuse.release.xcconfig"; path = "Target Support Files/Pods-fuse/Pods-fuse.release.xcconfig"; sourceTree = "<group>"; }; 7A4D352CD337FB3A3BF06240 /* Pods-fuse.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fuse.release.xcconfig"; path = "Target Support Files/Pods-fuse/Pods-fuse.release.xcconfig"; sourceTree = "<group>"; };
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = fuse/SplashScreen.storyboard; sourceTree = "<group>"; }; AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = fuse/SplashScreen.storyboard; sourceTree = "<group>"; };
B50056BB879EC1FE9A5251D0 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = fuse/PrivacyInfo.xcprivacy; sourceTree = "<group>"; }; B50056BB879EC1FE9A5251D0 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = fuse/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = "<group>"; }; BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = "<group>"; };
E3C56C9C8A70435F80C980CD /* fuse-Bridging-Header.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = "fuse-Bridging-Header.h"; path = "fuse/fuse-Bridging-Header.h"; sourceTree = "<group>"; }; E3C56C9C8A70435F80C980CD /* fuse-Bridging-Header.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = "fuse-Bridging-Header.h"; path = "fuse/fuse-Bridging-Header.h"; sourceTree = "<group>"; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
@ -273,8 +273,11 @@
); );
inputPaths = ( inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-fuse/Pods-fuse-resources.sh", "${PODS_ROOT}/Target Support Files/Pods-fuse/Pods-fuse-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/EXApplication/ExpoApplication_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/ExpoConstants_privacy.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/ExpoConstants_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/EXNotifications/ExpoNotifications_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoDevice/ExpoDevice_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoFileSystem/ExpoFileSystem_privacy.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/ExpoFileSystem/ExpoFileSystem_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoSystemUI/ExpoSystemUI_privacy.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/ExpoSystemUI/ExpoSystemUI_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNCAsyncStorage/RNCAsyncStorage_resources.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/RNCAsyncStorage/RNCAsyncStorage_resources.bundle",
@ -303,8 +306,11 @@
); );
name = "[CP] Copy Pods Resources"; name = "[CP] Copy Pods Resources";
outputPaths = ( outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoApplication_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoConstants_privacy.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoConstants_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoNotifications_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoDevice_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoFileSystem_privacy.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoFileSystem_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoSystemUI_privacy.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoSystemUI_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNCAsyncStorage_resources.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNCAsyncStorage_resources.bundle",
@ -385,9 +391,14 @@
"FB_SONARKIT_ENABLED=1", "FB_SONARKIT_ENABLED=1",
); );
INFOPLIST_FILE = fuse/Info.plist; INFOPLIST_FILE = fuse/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Fuse;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.lifestyle";
IPHONEOS_DEPLOYMENT_TARGET = 13.4; IPHONEOS_DEPLOYMENT_TARGET = 13.4;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = (
MARKETING_VERSION = 1.0; "$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.1;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
"-ObjC", "-ObjC",
@ -413,9 +424,14 @@
CODE_SIGN_ENTITLEMENTS = fuse/fuse.entitlements; CODE_SIGN_ENTITLEMENTS = fuse/fuse.entitlements;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
INFOPLIST_FILE = fuse/Info.plist; INFOPLIST_FILE = fuse/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Fuse;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.lifestyle";
IPHONEOS_DEPLOYMENT_TARGET = 13.4; IPHONEOS_DEPLOYMENT_TARGET = 13.4;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = (
MARKETING_VERSION = 1.0; "$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.1;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
"-ObjC", "-ObjC",
@ -483,14 +499,14 @@
IPHONEOS_DEPLOYMENT_TARGET = 13.4; IPHONEOS_DEPLOYMENT_TARGET = 13.4;
LD = ""; LD = "";
LDPLUSPLUS = ""; LDPLUSPLUS = "";
LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)"; LD_RUNPATH_SEARCH_PATHS = (
/usr/lib/swift,
"$(inherited)",
);
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\""; LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = "$(inherited) ";
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
USE_HERMES = true; USE_HERMES = true;
@ -542,13 +558,13 @@
IPHONEOS_DEPLOYMENT_TARGET = 13.4; IPHONEOS_DEPLOYMENT_TARGET = 13.4;
LD = ""; LD = "";
LDPLUSPLUS = ""; LDPLUSPLUS = "";
LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)"; LD_RUNPATH_SEARCH_PATHS = (
/usr/lib/swift,
"$(inherited)",
);
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\""; LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = "$(inherited) ";
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
USE_HERMES = true; USE_HERMES = true;

View File

@ -31,6 +31,12 @@
<string>com.gibbyb.fuse</string> <string>com.gibbyb.fuse</string>
</array> </array>
</dict> </dict>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>exp+fuse</string>
</array>
</dict>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1</string> <string>1</string>
@ -46,6 +52,8 @@
<key>NSUserActivityTypes</key> <key>NSUserActivityTypes</key>
<array> <array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string> <string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
</array> </array>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>SplashScreen</string> <string>SplashScreen</string>

View File

@ -4,6 +4,16 @@
<dict> <dict>
<key>NSPrivacyAccessedAPITypes</key> <key>NSPrivacyAccessedAPITypes</key>
<array> <array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
<string>0A2A.1</string>
<string>3B52.1</string>
</array>
</dict>
<dict> <dict>
<key>NSPrivacyAccessedAPIType</key> <key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string> <string>NSPrivacyAccessedAPICategoryUserDefaults</string>
@ -14,12 +24,10 @@
</dict> </dict>
<dict> <dict>
<key>NSPrivacyAccessedAPIType</key> <key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string> <string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key> <key>NSPrivacyAccessedAPITypeReasons</key>
<array> <array>
<string>0A2A.1</string> <string>35F9.1</string>
<string>3B52.1</string>
<string>C617.1</string>
</array> </array>
</dict> </dict>
<dict> <dict>
@ -31,14 +39,6 @@
<string>85F4.1</string> <string>85F4.1</string>
</array> </array>
</dict> </dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
</array> </array>
<key>NSPrivacyCollectedDataTypes</key> <key>NSPrivacyCollectedDataTypes</key>
<array/> <array/>

View File

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict/> <dict>
<key>aps-environment</key>
<string>development</string>
</dict>
</plist> </plist>

View File

@ -0,0 +1,58 @@
{
"name": "fuse",
"main": "expo-router/entry",
"version": "1.0.0",
"scripts": {
"start": "expo start",
"reset-project": "node ./scripts/reset-project.js",
"android": "expo run:android",
"ios": "expo run:ios",
"web": "expo start --web",
"test": "jest --watchAll",
"lint": "expo lint"
},
"jest": {
"preset": "jest-expo"
},
"dependencies": {
"@expo/vector-icons": "^14.0.2",
"@react-native-async-storage/async-storage": "^2.0.0",
"@react-native-community/datetimepicker": "^8.2.0",
"@react-navigation/native": "^6.0.2",
"axios": "^1.7.7",
"expo": "~51.0.28",
"expo-constants": "~16.0.2",
"expo-font": "~12.0.9",
"expo-linear-gradient": "~13.0.2",
"expo-linking": "~6.3.1",
"expo-router": "~3.5.23",
"expo-splash-screen": "~0.27.5",
"expo-status-bar": "~1.12.1",
"expo-system-ui": "~3.0.7",
"expo-web-browser": "~13.0.3",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-native": "0.74.5",
"react-native-dotenv": "^3.4.11",
"react-native-gesture-handler": "~2.16.1",
"react-native-reanimated": "~3.10.1",
"react-native-safe-area-context": "4.10.5",
"react-native-screens": "3.31.1",
"react-native-vector-icons": "^10.1.0",
"react-native-web": "~0.19.10",
"expo-dev-client": "~4.0.26",
"expo-notifications": "~0.28.17",
"expo-device": "~6.0.2"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@types/jest": "^29.5.12",
"@types/react": "~18.2.45",
"@types/react-test-renderer": "^18.0.7",
"jest": "^29.2.1",
"jest-expo": "~51.0.3",
"react-test-renderer": "18.2.0",
"typescript": "~5.3.3"
},
"private": true
}

File diff suppressed because it is too large Load Diff