I got pfps working basicallly
This commit is contained in:
150
components/auth/Profile_Avatar.tsx
Normal file
150
components/auth/Profile_Avatar.tsx
Normal file
@ -0,0 +1,150 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { supabase } from '@/lib/supabase'
|
||||
import { StyleSheet, Alert, Image, TouchableOpacity } from 'react-native'
|
||||
import * as ImagePicker from 'expo-image-picker'
|
||||
//import { ImageManipulator } from 'expo-image-manipulator';
|
||||
import { ThemedView, ThemedText, ThemedTextButton } from '../theme';
|
||||
import { IconSymbol } from '@/components/ui/IconSymbol';
|
||||
|
||||
interface Props {
|
||||
size: number
|
||||
url: string | null
|
||||
onUpload: (filePath: string) => void
|
||||
}
|
||||
|
||||
export default function Avatar({ url, size = 150, onUpload }: Props) {
|
||||
const [uploading, setUploading] = useState(false)
|
||||
const [avatarUrl, setAvatarUrl] = useState<string | null>(null)
|
||||
const avatarSize = { height: size, width: size }
|
||||
|
||||
useEffect(() => {
|
||||
if (url) downloadImage(url)
|
||||
}, [url])
|
||||
|
||||
async function downloadImage(path: string) {
|
||||
try {
|
||||
const { data, error } = await supabase.storage.from('avatars').download(path)
|
||||
|
||||
if (error) {
|
||||
throw error
|
||||
}
|
||||
|
||||
const fr = new FileReader()
|
||||
fr.readAsDataURL(data)
|
||||
fr.onload = () => {
|
||||
setAvatarUrl(fr.result as string)
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
console.log('Error downloading image: ', error.message)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
async function uploadAvatar() {
|
||||
try {
|
||||
setUploading(true)
|
||||
const { data: { user } } = await supabase.auth.getUser();
|
||||
|
||||
const result = await ImagePicker.launchImageLibraryAsync({
|
||||
mediaTypes: ImagePicker.MediaTypeOptions.Images, // Restrict to only images
|
||||
allowsMultipleSelection: false, // Can only select one image
|
||||
allowsEditing: true, // Allows the user to crop / rotate their photo before uploading it
|
||||
quality: 1,
|
||||
exif: false, // We don't want nor need that data.
|
||||
});
|
||||
|
||||
if (result.canceled || !result.assets || result.assets.length === 0) {
|
||||
console.log('User cancelled image picker.');
|
||||
return;
|
||||
}
|
||||
|
||||
//const manipulatedImage = await ImageManipulator.manipulate(result.assets[0].uri)
|
||||
//.resize({ width: 300 })
|
||||
//.renderAsync();
|
||||
|
||||
//const manipulateResult = await manipulateAsync(
|
||||
//result.assets[0].uri,
|
||||
//[{resize: {width: 300, height: 300}}],
|
||||
//{compress: 0.7, format: SaveFormat.JPEG}
|
||||
//);
|
||||
|
||||
const image = result.assets[0];
|
||||
console.log('Got image', image)
|
||||
|
||||
if (!image.uri) {
|
||||
throw new Error('No image uri!') // Realistically, this should never happen, but just in case...
|
||||
}
|
||||
|
||||
const arraybuffer = await fetch(image.uri).then((res) => res.arrayBuffer())
|
||||
|
||||
const fileExt = image.uri?.split('.').pop()?.toLowerCase() ?? 'jpeg'
|
||||
const path = `${Date.now()}.${fileExt}`
|
||||
const { data, error: uploadError } = await supabase.storage
|
||||
.from('avatars')
|
||||
.upload(path, arraybuffer, {
|
||||
contentType: image.mimeType ?? 'image/jpeg',
|
||||
});
|
||||
const { data: updateData, error: updateError } = await supabase
|
||||
.from('profiles')
|
||||
.update({ avatar_url: data?.path })
|
||||
.eq('id', user?.id);
|
||||
|
||||
if (uploadError) {
|
||||
throw uploadError
|
||||
}
|
||||
|
||||
onUpload(data.path)
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
Alert.alert(error.message)
|
||||
} else {
|
||||
throw error
|
||||
}
|
||||
} finally {
|
||||
setUploading(false)
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
onPress={uploadAvatar}
|
||||
style={styles.avatarContainer}
|
||||
>
|
||||
{avatarUrl ? (
|
||||
<Image source={{ uri: avatarUrl }} style={styles.avatar} />
|
||||
) : (
|
||||
<ThemedView style={styles.avatarPlaceholder}>
|
||||
<IconSymbol name="person.fill" size={50} color="#999" />
|
||||
</ThemedView>
|
||||
)}
|
||||
<ThemedText style={styles.changePhotoText}>Change Photo</ThemedText>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
avatarContainer: {
|
||||
alignItems: 'center',
|
||||
marginTop: 20,
|
||||
marginBottom: 30,
|
||||
},
|
||||
avatar: {
|
||||
width: 120,
|
||||
height: 120,
|
||||
borderRadius: 60,
|
||||
},
|
||||
avatarPlaceholder: {
|
||||
width: 120,
|
||||
height: 120,
|
||||
borderRadius: 60,
|
||||
backgroundColor: '#E1E1E1',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
changePhotoText: {
|
||||
marginTop: 8,
|
||||
color: '#007AFF',
|
||||
fontSize: 16,
|
||||
},
|
||||
});
|
Reference in New Issue
Block a user