diff --git a/contexts/audioContext.tsx b/contexts/audioContext.tsx index 160ce00..25ff205 100644 --- a/contexts/audioContext.tsx +++ b/contexts/audioContext.tsx @@ -2,9 +2,11 @@ import React, { useCallback, useContext, useEffect, useState } from "react"; import toast from "react-hot-toast"; import { KeyCode } from "../globals/keycode"; import MicRecorder from "mic-recorder-to-mp3"; +import { v4 as uuidv4 } from "uuid"; import AudioPlayer from "react-h5-audio-player"; import "react-h5-audio-player/lib/styles.css"; +import CloudStorageService from "../services/cloudStorageService"; interface AudioContextInterface { selectedTeammate: string; // can only have one selected @@ -48,6 +50,8 @@ function stopBothVideoAndAudio(stream) { }); } +const cloudStorageService = new CloudStorageService(); + export default function AudioContextProvider({ children }) { // SECTION: set up for shortcuts and recording and such const [selectedTeammate, setSelectedTeamMember] = useState(null); // id of selected teammate @@ -179,30 +183,29 @@ export default function AudioContextProvider({ children }) { ); } - // everything to do with audio file - async function stopRecording() { - recorder - .stop() - .getMp3() - .then(([buffer, blob]) => { - const blobURL = URL.createObjectURL(blob); + async function stopRecording(): Promise { + return new Promise((resolve, reject) => { + recorder + .stop() + .getMp3() + .then(([buffer, blob]) => { + const blobURL = URL.createObjectURL(blob); - const file = new File(buffer, "me-at-thevoice.mp3", { - type: blob.type, - lastModified: Date.now(), + const file = new File(buffer, uuidv4() + ".mp3", { + type: blob.type, + lastModified: Date.now(), + }); + + const player = new Audio(URL.createObjectURL(file)); + player.onended = onEndedPlaying; + player.play(); + + resolve(file); + }) + .catch((error) => { + reject(error.message); }); - - const player = new Audio(URL.createObjectURL(file)); - - console.log(URL.createObjectURL(file)); - - player.onended = onEndedPlaying; - - player.play(); - - toast.success("Audio Clip Sent"); - }) - .catch((e) => toast.error("Problem in sending clip")); + }); } function onEndedPlaying(e) { @@ -222,7 +225,24 @@ export default function AudioContextProvider({ children }) { console.log("stopped recording"); setIsRecording(false); - stopRecording(); + stopRecording() + .then((file) => { + console.log(file); + + // upload to cloud storage + return cloudStorageService.uploadMessageAudioFile(file); + }) + .then((downloadUrl) => { + console.log("file is stored: " + downloadUrl); + + // send message to firestore + + return; + }) + .then(() => {}) + .catch((error) => { + toast.error("Problem in sending clip"); + }); console.log("sending message to " + selectedTeammate); diff --git a/package-lock.json b/package-lock.json index 5eb861d..3585c9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,8 @@ "react-h5-audio-player": "^3.8.1", "react-hot-toast": "^2.2.0", "react-icons": "^4.3.1", - "react-moment": "^1.1.1" + "react-moment": "^1.1.1", + "uuid": "^8.3.2" }, "devDependencies": { "@types/react": "^17.0.38", @@ -8908,7 +8909,6 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "optional": true, "bin": { "uuid": "dist/bin/uuid" } @@ -16099,8 +16099,7 @@ "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "optional": true + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, "v8-compile-cache": { "version": "2.3.0", diff --git a/package.json b/package.json index 91413ab..d63edad 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ "react-h5-audio-player": "^3.8.1", "react-hot-toast": "^2.2.0", "react-icons": "^4.3.1", - "react-moment": "^1.1.1" + "react-moment": "^1.1.1", + "uuid": "^8.3.2" }, "devDependencies": { "@types/react": "^17.0.38", diff --git a/services/cloudStorageService.tsx b/services/cloudStorageService.tsx new file mode 100644 index 0000000..510f8cd --- /dev/null +++ b/services/cloudStorageService.tsx @@ -0,0 +1,75 @@ +import { + getDownloadURL, + getStorage, + ref, + uploadBytesResumable, +} from "firebase/storage"; + +export default class CloudStorageService { + private storage = getStorage(); + + /** + * return the + */ + async uploadMessageAudioFile(audioFile: File): Promise { + // Create the file metadata + /** @type {any} */ + const metadata = { + contentType: "audio/mpeg", + }; + + // Upload file and metadata to the object 'images/mountains.jpg' + const storageRef = ref(this.storage, "messages/" + audioFile.name); + const uploadTask = uploadBytesResumable(storageRef, audioFile, metadata); + + // Listen for state changes, errors, and completion of the upload. + return new Promise((resolve, reject) => { + uploadTask.on( + "state_changed", + (snapshot) => { + // Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded + const progress = + (snapshot.bytesTransferred / snapshot.totalBytes) * 100; + console.log("Upload is " + progress + "% done"); + switch (snapshot.state) { + case "paused": + console.log("Upload is paused"); + break; + case "running": + console.log("Upload is running"); + break; + } + }, + (error) => { + // A full list of error codes is available at + // https://firebase.google.com/docs/storage/web/handle-errors + + reject(new Error(error.message)); + + switch (error.code) { + case "storage/unauthorized": + // User doesn't have permission to access the object + break; + case "storage/canceled": + // User canceled the upload + break; + + // ... + + case "storage/unknown": + // Unknown error occurred, inspect error.serverResponse + break; + } + }, + () => { + // Upload completed successfully, now we can get the download URL + return getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => { + console.log("File available at", downloadURL); + + return resolve(downloadURL); + }); + } + ); + }); + } +} diff --git a/services/sendService.tsx b/services/sendService.tsx new file mode 100644 index 0000000..dddaedf --- /dev/null +++ b/services/sendService.tsx @@ -0,0 +1,3 @@ +export class SendService { + async sendMessage() {} +}