チャットApp(プロフィール作成・画像の登録)

今回は前回の登録・ログインの機能で登録したユーザのうち、メール・パスワードで登録したユーザ・匿名ユーザのユーザネームとプロフィール画像を登録する機能を追加しようと思います。
google, twitterのいわゆるOAuth機能を利用してログインしたユーザはすでにgoogle, twitter側で登録されたものを使用するので必要ありません。

FireStorageへの保存機能

画像などのファイルはfirestoreに直接保存することは出来ないので、firestorageに保存してそのパスをfirestoreに登録し、画像を呼び出すようにします。firestorageはこれまで扱ったことが無いので詳しく残そうと思います。とはいえfirebaseのドキュメントに書いてある通りにするだけなので、あまり難しいことはありません。

firebaseドキュメント

まず、プロフィールのページを作成します。return内にインプットタグをtype="file"で作成します。全体のコードは後にgithubのリポジトリを公開するのでそちらを確認ください。

profile/setting.tsx

<div className={ Styles.innerbox }>
   <BasicButton  
       fullWidth ={ true } 
   >
       <input 
           id        = "photoFile"
           type      ="file"
           accept    ="image/*"
           className ={ Styles.inputFile }
           onChange  ={ handlePhoto }
       />
   </BasicButton>
</div>

<div className={ Styles.innerbox }>
   <BasicButton
       fullWidth ={ true }
       disabled  ={ disable }
       onclick   ={ handleSaveUserData }
   >
       登録
   </BasicButton>
</div>

// 画像を選択すると変数photoにfileを代入
const handlePhoto = (event:React.ChangeEvent<{files: unknown}>) => {
   setPhoto(event.target.files[0]);
}

// 画像をfirestorageに保存
const handleSaveUserData = async() => {
   await saveUserImage(photo);
}

handlePhoto関数で画像ファイルを選択した時にファイルごと変数photoに代入するようにします。
handleSaveUserData内で別で定義したsaveUserImage関数で保存して見ます。いかにsaveUserImage関数を記します。

functions/storage.ts

import { FBstorage } from "./firebase";
export const saveUserImage = async(image) => {
   const imageName = image.name;
   const userImageRef = FBstorage.ref().child("userPhoto/" + imageName);
   userImageRef.put(image)
   .then(result => {
       console.log(result);
   })
   .catch(error => {
       console.log(error);
   });
}

これで実行してみると以下のようになり保存出来ていることがわかります。

スクリーンショット 2020-08-17 13.08.42

スクリーンショット 2020-08-17 13.13.56

これでfireStorageの保存のやり方は概ね把握したので、実際に機能を作っていきましょう。まずsaveUserImage関数を以下のように書き換えます。

functions/storage.ts

export const saveUserImage = async(image, uid:string):Promise<[boolean, string]> => {
   const fullPath = "userPhoto/" + uid + image.name;
   const userImageRef = FBstorage.ref().child(fullPath);
   let bool:boolean;
   await userImageRef.put(image)
   .then(() => {
       bool = true;
   })
   .catch(error => {
       console.log(error);
       bool = false;
   });
   return [bool, fullPath];
}

引数にユーザ固有のidであるuidを指定し、成功したら、ファイルまでのパスを返すようにします。

user情報のアップデート

画像が保存出来るようになったので、それに合わせてユーザの登録情報をアプデートします。

handleSazeUserdata関数を以下のように書き換えます。

profile/setting.tsx

const saveUserdata = (user:firebase.User, fullPath:string) => {
   user.updateProfile({
       displayName: username,
       photoURL   : fullPath,
   })
   .then(() => {
       console.log("save userdata success!!");
   })
   .catch(error => {
       console.log(error);
   });
}
const handleSaveUserData = async() => {
   if (UMessage[0] === "OK!!") {
       setDisable(true);
       if (await activeUserExist()) {
           const user = getActiveUser();
           if (photo) {
               const [bool, fullPath] = await saveUserImage(photo, user.uid);
               if (bool) {
                   saveUserdata(user, fullPath);
                   console.log(getActiveUser());
               }
           } else {
               saveUserdata(user, "userPhoto/default-user-image.png");
           }
       } else {
           alert("不具合でログインしていない状態になっているようです。もう一度登録処理からお願いします。");
       }
       setDisable(false);
   }
}

簡単に説明すると、まずusernameが入力されているかをUMessage変数から読み取り、activeUserExist関数でユーザがログイン状態かどうかを確認。ログイン状態なら、photo変数にアップロード画像が入れらていれば、fire storageに画像をアップロードし、返り値のパスとusernameを使い、saveUserdata関数でuser情報をアップデートする、という形になっています。
もし、画像がアップロードされていない場合はこちらが用意したdefault-user-image.pngをセットするようにしています。

登録と匿名認証で試して見ましたが上手く行っているようです。

スクリーンショット 2020-08-17 15.29.19

スクリーンショット 2020-08-17 15.27.46


この記事が気に入ったらサポートをしてみませんか?