ImageUploader.js (2847B)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | import { useState, forwardRef, useImperativeHandle } from "react"; import { ActivityIndicator, Alert, Button, Image, Platform, Text, View, } from "react-native"; import { launchImageLibraryAsync } from "expo-image-picker"; import { api } from "../services/api"; import { colors } from "../styles"; const ImageUploader = forwardRef(({ token }, ref) => { const [imageAsset, setImageAsset] = useState(null); const [isUploading, setIsUploading] = useState(false); useImperativeHandle(ref, () => ({ upload: async () => { if (!imageAsset) return null; setIsUploading(true); try { const imageUrl = await handleUpload(); return imageUrl; } catch (error) { Alert.alert("Upload Failed", error.message); return null; } finally { setIsUploading(false); } }, reset: () => { setImageAsset(null); setIsUploading(false); }, })); const pickImage = async () => { const result = await launchImageLibraryAsync({ allowsEditing: true, quality: 0.7, mediaTypes: "Images", }); if (!result.canceled) setImageAsset(result.assets[0]); }; const handleUpload = async () => { const data = new FormData(); if (Platform.OS === "web") { const response = await fetch(imageAsset.uri); const blob = await response.blob(); const fileName = imageAsset.fileName || `web-image-${Date.now()}.jpg`; data.append("image", blob, fileName); } else { data.append("image", { uri: imageAsset.uri, type: imageAsset.mimeType || "image/jpeg", name: imageAsset.fileName || imageAsset.uri.split("/").pop() || `image-${Date.now()}.jpg`, }); } const responseData = await api.uploadImage(data, token); return responseData.url; }; const removeImage = () => { setImageAsset(null); }; return ( <View style={{ marginVertical: 10 }}> {imageAsset && ( <View> <Image source={{ uri: imageAsset.uri }} style={{ width: "100%", height: 200, resizeMode: "contain", marginBottom: 10, }} /> <Button title="Remove Image" color={colors.danger} onPress={removeImage} /> </View> )} {isUploading ? ( <View style={{ alignItems: "center", padding: 20 }}> <ActivityIndicator size="large" color={colors.darkGreen} /> <Text>Uploading...</Text> </View> ) : ( !imageAsset && ( <Button title="Pick Image" color={colors.darkGreen} onPress={pickImage} /> ) )} </View> ); }); export default ImageUploader; |