1- import { View , Text , StyleSheet , TouchableOpacity , Image , FlatList } from 'react-native' ;
1+ import { View , StyleSheet , TouchableOpacity , ScrollView } from 'react-native' ;
22import React , { useEffect , useState } from 'react' ;
33import { Ionicons } from '@expo/vector-icons' ;
44import * as ImagePicker from 'expo-image-picker' ;
55import { useAuth } from '../../provider/AuthProvider' ;
6- import Uppy from '@uppy/core' ;
7- import Tus from '@uppy/tus' ;
8- import { TusFileReader } from '../../helper/tusFileReader' ;
96import * as FileSystem from 'expo-file-system' ;
107import { decode } from 'base64-arraybuffer' ;
11-
12- const SUPABASE_STORAGE_URL = 'https://kolrncrjvromhaivenfp.supabase.co/storage/v1/' ;
8+ import { supabase } from '../../config/initSupabase' ;
9+ import { FileObject } from '@supabase/storage-js' ;
10+ import ImageItem from '../../components/ImageItem' ;
1311
1412const list = ( ) => {
15- const { session } = useAuth ( ) ;
16- const [ uppy , setUppy ] = useState < Uppy > ( null ) ;
17- const [ progress , setProgress ] = useState ( 0 ) ;
18- const [ uploading , setUploading ] = useState ( false ) ;
19- const [ files , setFiles ] = useState ( [ ] ) ;
13+ const { user } = useAuth ( ) ;
14+ const [ files , setFiles ] = useState < FileObject [ ] > ( [ ] ) ;
2015
2116 useEffect ( ( ) => {
22- if ( ! session ) return ;
23-
24- const uppyInstance = new Uppy ( { debug : true , autoProceed : false } )
25- . use ( Tus , {
26- endpoint : `${ SUPABASE_STORAGE_URL } object/files/${ session . user . id } ` ,
27- // fileReader: new TusFileReader(), <- this is not working
28- // retryDelays: [0, 3000, 5000, 10000, 20000],
29- // uploadDataDuringCreation: true,
30- headers : {
31- authorization : `Bearer ${ session . access_token } ` ,
32- 'x-upsert' : 'true' ,
33- } ,
34- chunkSize : 6 * 1024 * 1024 ,
35- allowedMetaFields : [ 'bucketName' , 'objectName' , 'contentType' , 'cacheControl' ] ,
36- } )
17+ if ( ! user ) return ;
3718
38- . on ( 'file-added' , ( file ) => {
39- file . meta = {
40- ...file . meta ,
41- bucketName : `files` ,
42- objectName : `${ session . user . id } /${ file . name } ` ,
43- contentType : file . type ,
44- } ;
45- console . log ( 'file-added:' , file ) ;
46- } )
47- . on ( 'upload-progress' , ( file , progress ) => {
48- console . log ( 'upload-progress:' , progress ) ;
19+ // Load user images
20+ loadImages ( ) ;
21+ } , [ user ] ) ;
4922
50- setProgress ( progress . bytesUploaded / progress . bytesTotal ) ;
51- } )
52- . on ( 'complete' , ( result ) => {
53- console . log ( 'complete:' , result ) ;
54- setFiles ( [ ] ) ;
55- setUploading ( false ) ;
56- } )
57- . on ( 'progress' , ( progress ) => {
58- console . log ( 'progress:' , progress ) ;
59- } )
60- . on ( 'error' , ( error ) => {
61- console . log ( 'error:' , JSON . stringify ( error ) ) ;
62- } ) ;
63-
64- setUppy ( uppyInstance ) ;
65- } , [ session ] ) ;
23+ const loadImages = async ( ) => {
24+ const { data } = await supabase . storage . from ( 'files' ) . list ( user . id ) ;
25+ setFiles ( data ) ;
26+ } ;
6627
6728 const onSelectImage = async ( ) => {
6829 const options : ImagePicker . ImagePickerOptions = {
@@ -74,84 +35,29 @@ const list = () => {
7435
7536 // Save image if not cancelled
7637 if ( ! result . canceled ) {
77- // UPPY APPROACH
7838 const img = result . assets [ 0 ] ;
79- const fetchResponse = await fetch ( img . uri ) ;
80- const blob = await fetchResponse . blob ( ) ;
81- console . log ( '🚀 ~ file: list.tsx:83 ~ onSelectImage ~ blob:' , blob ) ;
39+ const base64 = await FileSystem . readAsStringAsync ( img . uri , { encoding : 'base64' } ) ;
40+ const filePath = `${ user . id } /${ new Date ( ) . getTime ( ) } .${ img . type === 'image' ? 'png' : 'mp4' } ` ;
8241 const contentType = img . type === 'image' ? 'image/png' : 'video/mp4' ;
83- const fileName = `${ new Date ( ) . getTime ( ) } .${ img . type === 'image' ? 'png' : 'mp4' } ` ;
84- console . log ( '🚀 ~ file: list.tsx:87 ~ onSelectImage ~ fileName:' , fileName ) ;
85-
86- // Add file to uppy with blob data
87- uppy . addFile ( {
88- id : fileName ,
89- name : fileName ,
90- type : blob . type ,
91- data : blob ,
92- size : blob . size ,
93- } ) ;
94-
95- // Add image to local files array
96- setFiles ( ( old ) => [ ...old , { uri : img . uri , fileName, contentType } ] ) ;
97-
98- // SUPABASE STANDARD APPROACH
99- // THIS WORKS
100- // const img = result.assets[0];
101- // const base64 = await FileSystem.readAsStringAsync(img.uri, { encoding: 'base64' });
102- // const filePath = `${user.id}/${new Date().getTime()}.${img.type === 'image' ? 'png' : 'mp4'}`;
103- // const contentType = img.type === 'image' ? 'image/png' : 'video/mp4';
104- // let { error, data } = await supabase.storage.from('files').upload(filePath, decode(base64), { contentType });
105- // console.log('error', error);
106- // console.log('data', data);
42+ await supabase . storage . from ( 'files' ) . upload ( filePath , decode ( base64 ) , { contentType } ) ;
43+ loadImages ( ) ;
10744 }
10845 } ;
10946
110- const onUpload = async ( ) => {
111- uppy . upload ( ) ;
112- setUploading ( true ) ;
113- } ;
114-
115- const onPause = async ( ) => {
116- uppy . pauseAll ( ) ;
117- setUploading ( false ) ;
118- } ;
119-
120- const onResume = async ( ) => {
121- uppy . resumeAll ( ) ;
122- setUploading ( true ) ;
123- } ;
124-
125- // Render image list item
126- const renderItem = ( { item } : { item : any } ) => {
127- return (
128- < View style = { { flexDirection : 'row' , margin : 1 , alignItems : 'center' , gap : 5 } } >
129- < Image style = { { width : 80 , height : 80 } } source = { { uri : item . uri } } />
130- < Text style = { { flex : 1 , color : '#fff' } } > { item . fileName } </ Text >
131- </ View >
132- ) ;
47+ const onRemoveImage = async ( item : FileObject , listIndex : number ) => {
48+ supabase . storage . from ( 'files' ) . remove ( [ `${ user . id } /${ item . name } ` ] ) ;
49+ const newFiles = [ ...files ] ;
50+ newFiles . splice ( listIndex , 1 ) ;
51+ setFiles ( newFiles ) ;
13352 } ;
13453
13554 return (
13655 < View style = { styles . container } >
137- { /* Progress bar */ }
138- { uploading && < View style = { { width : `${ progress } %` , height : 4 , backgroundColor : '#fff' , marginBottom : 10 , borderRadius : 2 } } /> }
139-
140- { /* Row with 3 buttons to start, pause and resume uploads */ }
141- < View style = { { flexDirection : 'row' , justifyContent : 'space-evenly' } } >
142- < TouchableOpacity onPress = { onUpload } style = { styles . button } >
143- < Text style = { { color : '#fff' } } > Upload</ Text >
144- </ TouchableOpacity >
145- < TouchableOpacity onPress = { onPause } style = { styles . button } >
146- < Text style = { { color : '#fff' } } > Pause</ Text >
147- </ TouchableOpacity >
148- < TouchableOpacity onPress = { onResume } style = { styles . button } >
149- < Text style = { { color : '#fff' } } > Resume</ Text >
150- </ TouchableOpacity >
151- </ View >
152-
153- { /* List of images to upload */ }
154- < FlatList data = { files } renderItem = { renderItem } style = { { marginTop : 50 } } />
56+ < ScrollView >
57+ { files . map ( ( item , index ) => (
58+ < ImageItem key = { item . id } item = { item } userId = { user . id } onRemoveImage = { ( ) => onRemoveImage ( item , index ) } />
59+ ) ) }
60+ </ ScrollView >
15561
15662 { /* FAB to add images */ }
15763 < TouchableOpacity onPress = { onSelectImage } style = { styles . fab } >
@@ -179,12 +85,6 @@ const styles = StyleSheet.create({
17985 backgroundColor : '#2b825b' ,
18086 borderRadius : 100 ,
18187 } ,
182- button : {
183- borderWidth : 2 ,
184- borderColor : '#2b825b' ,
185- padding : 12 ,
186- borderRadius : 4 ,
187- } ,
18888} ) ;
18989
19090export default list ;
0 commit comments