nice working uploading files and such
This commit is contained in:
+43
-23
@@ -2,9 +2,11 @@ import React, { useCallback, useContext, useEffect, useState } from "react";
|
|||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { KeyCode } from "../globals/keycode";
|
import { KeyCode } from "../globals/keycode";
|
||||||
import MicRecorder from "mic-recorder-to-mp3";
|
import MicRecorder from "mic-recorder-to-mp3";
|
||||||
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
|
||||||
import AudioPlayer from "react-h5-audio-player";
|
import AudioPlayer from "react-h5-audio-player";
|
||||||
import "react-h5-audio-player/lib/styles.css";
|
import "react-h5-audio-player/lib/styles.css";
|
||||||
|
import CloudStorageService from "../services/cloudStorageService";
|
||||||
|
|
||||||
interface AudioContextInterface {
|
interface AudioContextInterface {
|
||||||
selectedTeammate: string; // can only have one selected
|
selectedTeammate: string; // can only have one selected
|
||||||
@@ -48,6 +50,8 @@ function stopBothVideoAndAudio(stream) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cloudStorageService = new CloudStorageService();
|
||||||
|
|
||||||
export default function AudioContextProvider({ children }) {
|
export default function AudioContextProvider({ children }) {
|
||||||
// SECTION: set up for shortcuts and recording and such
|
// SECTION: set up for shortcuts and recording and such
|
||||||
const [selectedTeammate, setSelectedTeamMember] = useState<string>(null); // id of selected teammate
|
const [selectedTeammate, setSelectedTeamMember] = useState<string>(null); // id of selected teammate
|
||||||
@@ -179,30 +183,29 @@ export default function AudioContextProvider({ children }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// everything to do with audio file
|
async function stopRecording(): Promise<File> {
|
||||||
async function stopRecording() {
|
return new Promise((resolve, reject) => {
|
||||||
recorder
|
recorder
|
||||||
.stop()
|
.stop()
|
||||||
.getMp3()
|
.getMp3()
|
||||||
.then(([buffer, blob]) => {
|
.then(([buffer, blob]) => {
|
||||||
const blobURL = URL.createObjectURL(blob);
|
const blobURL = URL.createObjectURL(blob);
|
||||||
|
|
||||||
const file = new File(buffer, "me-at-thevoice.mp3", {
|
const file = new File(buffer, uuidv4() + ".mp3", {
|
||||||
type: blob.type,
|
type: blob.type,
|
||||||
lastModified: Date.now(),
|
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) {
|
function onEndedPlaying(e) {
|
||||||
@@ -222,7 +225,24 @@ export default function AudioContextProvider({ children }) {
|
|||||||
console.log("stopped recording");
|
console.log("stopped recording");
|
||||||
setIsRecording(false);
|
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);
|
console.log("sending message to " + selectedTeammate);
|
||||||
|
|
||||||
|
|||||||
Generated
+3
-4
@@ -18,7 +18,8 @@
|
|||||||
"react-h5-audio-player": "^3.8.1",
|
"react-h5-audio-player": "^3.8.1",
|
||||||
"react-hot-toast": "^2.2.0",
|
"react-hot-toast": "^2.2.0",
|
||||||
"react-icons": "^4.3.1",
|
"react-icons": "^4.3.1",
|
||||||
"react-moment": "^1.1.1"
|
"react-moment": "^1.1.1",
|
||||||
|
"uuid": "^8.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^17.0.38",
|
"@types/react": "^17.0.38",
|
||||||
@@ -8908,7 +8909,6 @@
|
|||||||
"version": "8.3.2",
|
"version": "8.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||||
"optional": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"uuid": "dist/bin/uuid"
|
"uuid": "dist/bin/uuid"
|
||||||
}
|
}
|
||||||
@@ -16099,8 +16099,7 @@
|
|||||||
"uuid": {
|
"uuid": {
|
||||||
"version": "8.3.2",
|
"version": "8.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"v8-compile-cache": {
|
"v8-compile-cache": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
|
|||||||
+2
-1
@@ -20,7 +20,8 @@
|
|||||||
"react-h5-audio-player": "^3.8.1",
|
"react-h5-audio-player": "^3.8.1",
|
||||||
"react-hot-toast": "^2.2.0",
|
"react-hot-toast": "^2.2.0",
|
||||||
"react-icons": "^4.3.1",
|
"react-icons": "^4.3.1",
|
||||||
"react-moment": "^1.1.1"
|
"react-moment": "^1.1.1",
|
||||||
|
"uuid": "^8.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^17.0.38",
|
"@types/react": "^17.0.38",
|
||||||
|
|||||||
@@ -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<string | Error> {
|
||||||
|
// 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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export class SendService {
|
||||||
|
async sendMessage() {}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user