繁体   English   中英

从 expo 图像选择器获取图像到 firebase db 中的用户 photoURL

[英]Get image from expo image picker to users photoURL in firebase db

我的应用程序当前的问题是通过 firebase/expo 设置用户个人资料图片。 当用户最初登录时,他们被添加到我的 firestore 数据库“用户”中,uid 为 email 等。然后一旦他们登录/注册,我想在设置屏幕中实现一个功能来上传图片。 我有 expo 图像选择器库正常工作,但它不是登录用户独有的,如果用户注销/重新加载应用程序,它就会消失。 要以正确的方式实现这一点,我是否还必须另外使用 firebase 存储空间。 我是否必须将此添加到每个用户文档并添加图像:使用来自 expo 图像选择器的值?

**包含用于选择用户头像的设置页面的主仪表板/设置屏幕:


//imports
import React from 'react'
import { getStorage, ref, uploadBytes } from "firebase/storage";
import {db} from './firebase'
import { collection } from 'firebase/firestore';
import { doc,setDoc,updateDoc } from 'firebase/firestore';
import { StyleSheet, Text, View, SafeAreaView , Image, TextInput, Button,StatusBar,Modal,Pressable,Switch} from 'react-native';
import * as Device from 'expo-device';
import * as Notifications from 'expo-notifications';
import * as ImagePicker from 'expo-image-picker';
import { Platform } from 'react-native';
import { Feed } from './components/Feed';
import { Profile } from './components/Profile';
import { NavigationContainer } from '@react-navigation/native';
import { createMaterialBottomTabNavigator } from '@react-navigation/material-bottom-tabs';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { Notifications1 } from './components/Notifications1';
import {auth} from "./firebase"
import { Ionicons } from '@expo/vector-icons'; 
import { FontAwesome5 } from '@expo/vector-icons'; 
import { Entypo } from '@expo/vector-icons'; 
import { useState } from 'react';
import { MaterialIcons } from '@expo/vector-icons'; 
import {  deleteUser } from "firebase/auth";
import { useEffect ,useRef} from 'react';
import { Appearance, useColorScheme } from 'react-native';
import Forums from "./components/Forums"
import { setStatusBarNetworkActivityIndicatorVisible } from 'expo-status-bar';

//tabs
const Tab = createMaterialBottomTabNavigator();


export const Login = ({setLoggedIn}) => {
  //state
  const currentUser = auth.currentUser;
  const uid = currentUser.uid
  const avatar = currentUser.photoURL  
  const [image, setImage] = useState("");
  //functions
  const pickImage = async () => {
    try {
 // No permissions request is necessary for launching the image library
    let result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.All,
      allowsEditing: true,
      aspect: [4, 3],
      quality: 1,
    });

   console.log(result);

    if (!result.canceled) {
      auth.currentUser.photoURL = result.uri
      setImage(result.uri);
    }
    await updateDoc(doc(db, "users", uid, {
      photoURL: result.uri.toString()
    }))
    }
    catch(E) {
      alert(E)
    }

  };
  const storage = getStorage();
  const storageRef = ref(storage, 'some-child');
  
  // 'file' comes from the Blob or File API
  uploadBytes(storageRef, file).then((snapshot) => {
    console.log('Uploaded a blob or file!');
  });
  
  
  const username = auth.currentUser.email.replace(/@gmail.com/, '').replace(/@yahoo.com/, '').replace(/@aol.com/, '').toUpperCase()
  const [modalVisible, setModalVisible] = useState(false);
  const [isEnabled, setIsEnabled] = useState(false);
  const toggleSwitch = () => {
    setIsEnabled(previousState => !previousState)
    colorScheme === "dark"
  };
  const user = auth.currentUser;
function deleteACC () {
  deleteUser(user).then(() => {
    setLoggedIn(false)
  }).catch((error) => {
   alert(error)
  });
  
}
const colorScheme = useColorScheme();
useEffect(()=>{
  const colorScheme = Appearance.getColorScheme();
    if (colorScheme === 'dark') {
       setIsEnabled(true); // true means dark
    }else{
       setIsEnabled(false); // false means light
    }
    registerForPushNotificationsAsync()
},[])
  if (colorScheme === 'dark') {
  } else {
    // render some light thing
  }
    registerForPushNotificationsAsync = async () => {
      
    
      if (Platform.OS === 'android') {
        Notifications.setNotificationChannelAsync('default', {
          name: 'default',
          importance: Notifications.AndroidImportance.MAX,
          vibrationPattern: [0, 250, 250, 250],
          lightColor: '#FF231F7C',
        });
      }
    };
  
  
  return (
    <View style={styles3.maincont}>
            <StatusBar hidden />
            <Modal
        animationType="slide"
        transparent={true}
        visible={modalVisible}
        onRequestClose={() => {
          Alert.alert('Modal has been closed.');
          setModalVisible(!modalVisible);
        }}>
        <View style={styles3.centeredView}>
          <View style={styles3.modalView}>
          <View style={styles3.modalview2}> 
            <Text style={styles3.modalText}>Settings:</Text>
            <Text style={styles3.hi}>Hello,  <Text style={styles3.helloUsername}>{username}</Text></Text>
            <View style={styles3.imagemocont}>
            <Button title="Pick an image from camera roll" onPress={pickImage} />
    <Image source={{ uri: `${currentUser.photoURL ? currentUser.photoURL : "https://media.istockphoto.com/id/1248723171/vector/camera-photo-upload-icon-on-isolated-white-background-eps-10-vector.jpg?s=612x612&w=0&k=20&c=e-OBJ2jbB-W_vfEwNCip4PW4DqhHGXYMtC3K_mzOac0="}` }} style={{ width: 200, height: 200,borderRadius:500 }} />
            </View>
            </View>
           <View style={{flexDirection:"row", alignItems:"center",marginBottom:15}}>
           <Text style={{marginRight:20}}>Dark Mode:</Text>
            <Switch
        trackColor={{ false: "#767577", true: "#81b0ff" }}
        thumbColor={isEnabled ? "#f5dd4b" : "#f4f3f4"}
        ios_backgroundColor="#3e3e3e"
        onValueChange={toggleSwitch}
        value={isEnabled}
      />
           </View>
           <View style={{width:"100%"}}>
            <View style={{backgroundColor:"#D9D9D9",padding:15,borderRadius:20,marginBottom:15}}>
            <Text style={{color:"#3A84EC",fontWeight:"700",textDecorationLine:"underline"}}>FAQ -  POPULAR ASKED QUESTIONS</Text>
            </View>
            <View style={{backgroundColor:"#D9D9D9",padding:15,borderRadius:20,marginBottom:15}}>
            <Text style={{color:"#3A84EC",fontWeight:"700",textDecorationLine:"underline"}}>Leave us a review </Text>
            </View>
            <View style={{backgroundColor:"#D9D9D9",padding:15,borderRadius:20,marginBottom:15}}  >
            <Text style={{color:"#3A84EC",fontWeight:"700",textDecorationLine:"underline"}} onPress={() => registerForPushNotificationsAsync()}>Notifications</Text>
            </View>
            <View style={{backgroundColor:"#D9D9D9",padding:15,borderRadius:20,marginBottom:15}}>
            <Text style={{color:"#3A84EC",fontWeight:"700",textDecorationLine:"underline"}}>About us</Text>
            </View> 
           </View>
          <View style={{width:"100%"}}>
          <View style={styles3.deleteacc}>
        <Button onPress={(e) => deleteACC()} color="#fff" title="delete account" />
        </View>
          <View style={styles3.signout}>
        <Button onPress={(e) => {setLoggedIn(false)}} color="#fff" title="sign out" />
        </View>
        <Pressable
              style={[styles3.button, styles3.buttonClose]}
              onPress={() => setModalVisible(!modalVisible)}>
              <Text style={styles3.textStyle}>Cancel</Text>
            </Pressable>
          </View>
          </View>
        </View>
      </Modal>
           <View style={styles3.logoCont}>
{/**
 *         <View style={{flexDirection: "row"}}>
        <View style={styles3.logostco}>
           <Image style={{height: 40,width:40}} source={{
            uri: "https://cdn.discordapp.com/attachments/783336191529320498/1034953013695103017/Screen_Shot_2022-10-26_at_6.13.27_PM.png"
           }}/>
          </View>
         <View style={styles3.eve2co}>
         <Text style={styles3.logo}>EVENNTII</Text>
         </View>
        </View>
 */}
         <View style={styles3.bottomcont}>
         <View>
              <Image source={{
                uri:`${auth.currentUser.photoURL}`
              }} style={{width:48,height:48,borderRadius:500,marginRight:10,borderColor:"#3A84EC",borderWidth:3}}/>
            </View>
         <Text style={styles3.username}>{username}</Text>
         </View>
         <Pressable style={[styles3.button, styles3.buttonOpen]} onPress={() => setModalVisible(true)}>
         <Entypo name="dots-three-vertical" size={24} color="black" />

      </Pressable>
        </View>
    <NavigationContainer 
>
      <Tab.Navigator
      initialRouteName="Feed"
      activeColor="#8DB7F3"
      inactiveColor='#3A84EC'
      barStyle={{ backgroundColor: '#fff' }}
    >
     <Tab.Screen
        name="Feed"
        component={Feed}
        options={{
          tabBarLabel: 'News',
          tabBarIcon: ({ color }) => (
            <Ionicons name="ios-newspaper-sharp" size={30} color={color} />
          ),
        }}
      />
     
           <Tab.Screen
        name="Forums"
        component={Forums}
        options={{
          tabBarLabel: 'Forums',
          tabBarIcon: ({ color }) => (
            <MaterialIcons name="forum" size={24} color={color} />
          ),
        }}
      />
      <Tab.Screen
        name="Notifications"
        component={Notifications1}
        options={{
          tabBarLabel: 'Crypto',
          tabBarIcon: ({ color }) => (
            <FontAwesome5 name="chart-area" size={26} color={color}/>
          ),
        }}
      />
      <Tab.Screen
        name="Profile"
        setParams={setLoggedIn}
        component={Profile}
        options={{
          tabBarLabel: `NFT's`,
          tabBarIcon: ({ color }) => (
            <MaterialCommunityIcons name="account" color={color} size={26} />
          ),
        }}
      />
    </Tab.Navigator>
      </NavigationContainer>
    </View>
  )
}


//push notifcations

async function schedulePushNotification() {
  await Notifications.scheduleNotificationAsync({
    content: {
      title: "You've got mail! 📬",
      body: 'Here is the notification body',
      data: { data: 'goes here' },
    },
    trigger: { seconds: 2 },
  });
}

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;
    }
    token = (await Notifications.getExpoPushTokenAsync()).data;
    console.log(token);
  } else {
    alert('Must use physical device for Push Notifications');
  }

  return token;
}
Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: false,
    shouldSetBadge: false,
  }),
});

**火力基地配置:

import { initializeApp } from "firebase/app";
import { getAuth, createUserWithEmailAndPassword,signOut} from "firebase/auth";
import { getFirestore } from "firebase/firestore";
import { getStorage, ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";

import {REACT_APP_API_KEY} from '@env'
import { useEffect } from "react";
const firebaseConfig = {
  apiKey: REACT_APP_API_KEY,
  SECRET INFO}

const myApp = initializeApp(firebaseConfig);
export  const auth = getAuth();
export const user = auth.currentUser;
export function createUser (auth, email, password) {
  createUserWithEmailAndPassword(auth, email, password)
  .then((userCredential) => {
    // Signed in 
    const user = userCredential.user;
    // ...
  })
  .catch((error) => {
    const errorCode = error.code;
    const errorMessage = error.message;
    // ..
  });
}

export default function signOutUser () {
  signOut(auth).then(() => {
    // Sign-out successful.
  }).catch((error) => {
    // An error happened.
  });
  
}
export const db = getFirestore(myApp);
export const storage = getStorage(myApp);

**将用户添加到数据库的注册逻辑:

export const Main = ({setLoggedIn}) => {
  // state 
  const [email, setEmail] = useState("")
  const [slideim, setslideIm] =useState([])
  const [password,setPassword] = useState("")
  const [emaillo, setEmaillo] = useState("")
  const [passwordlo,setPasswordlo] = useState("")
  const [spim,setSpIm] = useState("")
  const [modalVisible, setModalVisible] = useState(false);
  const uid = auth.currentUser.uid
// functions for auth
  const handleForm = () => {
    createUserWithEmailAndPassword(auth, email, password)
    .then(async (userCredential) => {
      // Signed in
      const user = userCredential.user;

      try {
        const docRef = await addDoc(collection(db, "users"), {
          email:email,
          password:password,
          uid:uid
        });
        console.log("Document written with ID: ", docRef.id);
      } catch (e) {
        console.error("Error adding document: ", e);
      }

      //=================
    })
    .catch((error) => {
      const errorCode = error.code;
      const errorMessage = error.message;
      alert(`a error occured ${errorCode}`)
    });
  }
  const handleLogin = () => {
    signInWithEmailAndPassword(auth, email, password)
  .then((userCredential) => {
    console.log(auth.settings)
    // Signed in 
    const user = userCredential.user;
  // ...
  })
  .catch((error) => {
    alert(error)
  });

  }
  const forgotPassword = async (email) => {
    return sendPasswordResetEmail(auth, email).then((a) => {
      alert("Password reset email sent")
    }).catch(e => alert(e))
  }

  // coinbase open code
  const [request, response, promptAsync] = useAuthRequest(
    {
      clientId: CLIENT_ID,
      scopes: ["wallet:accounts:read"],
      redirectUri,
    },
    discovery
  );
  const {
    // The token will be auto exchanged after auth completes.
    token,
    exchangeError,
  } = useAutoExchange(
    response?.type === "success" ? response.params.code  : null
  );

  React.useEffect(() => {
    if (token) {
      console.log("My Token:", token.accessToken);
    }
  }, [token]);
  const { width, height } = Dimensions.get('window');

  return (
    <View style={styles2.overallCont}>
      <StatusBar hidden />
        {/** */}
        {/**
         *  <View style={styles2.logoCont}>
          <View style={styles2.logostco}>
            <Text style={styles2.logostcote}>E</Text>
          </View>
         <Text style={styles2.logo}>EVENTEE</Text>
        </View>
         */}
        {/** */}
        <View style={styles2.disimagco}>
          <View>
            <Image style={styles2.logoImage} source={{
              uri:"https://cdn.discordapp.com/attachments/783336191529320498/1041428064955019324/Screen_Shot_2022-11-13_at_2.03.15_PM.png"
            }}/>
          </View> 
          </View>
      <View style={styles2.bottom1}>
        <Image source={{
          uri:`https://cronuts.digital/wp-content/uploads/2022/01/5402207-scaled.jpg`
        }} style={styles2.mainImage}/>
        <View style={styles2.disTeCo}>
          <Text style={styles2.disblu}>
          Discover Rare NFT and Crypto Analytics 
          </Text>
          {/** */}
        </View>
        {/** */}
        <View style={styles2.signupCo}>
          <View style={styles2.siteco}> 
          <Text style={styles2.maindesc}>NFTs and Crypto have exciting new properties: they’re unique, provably scarce, and usable across multiple applications.</Text>
          </View>
          <View style={styles2.teinpuco}>
            <TextInput value={email} onChangeText={value => {setEmail(value)}} color="#fff" style={styles2.textinpu} placeholder="Enter your email..."         autoCapitalize='none' placeholderTextColor="#EDEDED"/>
            <TextInput value={password} onChangeText={value => {setPassword(value)}}  placeholderTextColor="#EDEDED" color="#fff" style={styles2.textinpu} secureTextEntry autoCapitalize="none"
        placeholder="Enter your password..."/>
            <View style={styles2.buttonco}>
            <Button  onPress={handleLogin} color="white"  title="Sign In"  style={styles2.buttonsi} />
            </View>
            <View style={styles2.coinbasec}>
            <Button title="Coinbase Connect"color="white"  disabled={!request}
      onPress={() => {
        promptAsync();
      }}/>
            </View>
         {/**
          *    <View style={{flexDirection:"row",alignItems:"center",justifyContent:"center"}}>
              <Image style={{width:"70%",height:40,borderRadius:10,marginTop:10}} source={{
                uri:"https://cdn.discordapp.com/attachments/783336191529320498/1037903445790826627/Screen_Shot_2022-11-03_at_9.37.38_PM.png"
              }}/>
            </View>
          */}
            <Modal
                  animationType="slide"
                  transparent={true}
                  visible={modalVisible}
                  onRequestClose={() => {
                    Alert.alert("Modal has been closed.");
                    setModalVisible(!modalVisible);
                  }}
                >
                    <View style={styles2.modalView}>
                    <Image source={{
                        uri: "https://www.modernretail.co/wp-content/uploads/sites/5/2022/01/blockchain-explained-gif.gif"
                      }} style={{width: "100%",height: 380, position: "relative",bottom: 0,}}/>
                      <Text style={styles2.modalText}>Get Started</Text>
                      
                      <View style={{
                        width: "100%"
                      }}>
                        <Text style={styles2.teinhe}>Email</Text>
                      <TextInput value={email} onChangeText={value => {setEmail(value)}} color="#fff" style={styles2.textinpu} placeholder="Enter your email..."         autoCapitalize='none'/>
                      <Text style={styles2.teinhe}>Password</Text>
                      <TextInput value={password} onChangeText={value => {setPassword(value)}} color="#fff" style={styles2.textinpu} secureTextEntry autoCapitalize="none"
                        placeholder="Enter your password..."/>
                        <Text onPress={(email) => forgotPassword(email)} style={{textDecorationLine:"underline",color:"#fff",marginBottom:10}}>Forgot Password?</Text>
                   <View style={{
                        backgroundColor: "#4D76D8",
                        borderRadius: 10,
                        padding: 7
                   }} >
                    <Button  type="submit" onPress={handleForm} color="white"  title="Get Started"   />
                  </View> 
                      </View>
                      <Pressable
                        style={{
                          color: "white"
                        }}
                        onPress={() => setModalVisible(!modalVisible)}
                      >
                        <Text style={styles2.textStyle}>Cancel</Text>
                      </Pressable>
                  
                  </View>
           </Modal>
           <Pressable
              style={[styles2.button]}
              onPress={() => setModalVisible(!modalVisible)}
            >
             <Text style={styles2.donthaveAcc}>Dont Have An Account?</Text>
            </Pressable>
          </View>
        </View>
        </View>

   
      </View> 
  )
}

上面的代码给了我各种各样的错误,包括没有正确地将 expo 图像选择器库中的图像放入 firebase 中的用户文档。我该如何解决这个问题? **参考这段代码给我的问题最多:

await updateDoc(doc(db, "users", uid, {
          photoURL: result.uri.toString()
        }))
        }

从图像选择器上传图像到谷歌云存储 -> 接收上传成功后返回的图像 Url -> 将其保存在 Firestore -> 需要时从 firestore 接收图像 url

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM