diff --git a/packages/common/services/userService.ts b/packages/common/services/userService.ts index 95cb710..e929f77 100644 --- a/packages/common/services/userService.ts +++ b/packages/common/services/userService.ts @@ -27,7 +27,6 @@ export default class UserService { const docSnap = await getDoc(docRef); if (docSnap.exists()) { - console.log("got user data"); let user: User = docSnap.data() as User; return user; } else { diff --git a/packages/web/components/MainTabsOrPages/Conversations.tsx b/packages/web/components/MainTabsOrPages/Conversations.tsx index 05e03e4..9e7d6e3 100644 --- a/packages/web/components/MainTabsOrPages/Conversations.tsx +++ b/packages/web/components/MainTabsOrPages/Conversations.tsx @@ -32,7 +32,6 @@ export default function Conversations() { RelativeTimeSeparatedConvosSelector ); - console.log(relativeConvoSections); const todayConvos = relativeConvoSections.get( RelativeTimeConvosSections.today ); diff --git a/packages/web/components/MainTabsOrPages/Priority.tsx b/packages/web/components/MainTabsOrPages/Priority.tsx index b67b26e..65b1469 100644 --- a/packages/web/components/MainTabsOrPages/Priority.tsx +++ b/packages/web/components/MainTabsOrPages/Priority.tsx @@ -1,6 +1,6 @@ import { Avatar, Tooltip, Badge } from "antd"; import React from "react"; -import { useRecoilValue, useSetRecoilState } from "recoil"; +import { useRecoilValue, useSetRecoilState, useRecoilState } from "recoil"; import { FaCircle, FaMicrophone, @@ -9,6 +9,8 @@ import { FaUser, } from "react-icons/fa"; import { + hasMicPermissionsAtom, + isRecordingAtom, priorityConvosSelector, selectedPriorityConvoAtom, } from "../../recoil/main"; @@ -16,6 +18,13 @@ import PriorityConvoRow from "../Conversations/PriorityConvoRow"; import { configure, GlobalHotKeys, HotKeys, KeyMap } from "react-hotkeys"; import { useEffect, useState } from "react"; import toast from "react-hot-toast"; +import MicRecorder from "mic-recorder-to-mp3"; +import { v4 as uuidv4 } from "uuid"; + +// New instance +const recorder = new MicRecorder({ + bitRate: 128, +}); const MAX_SHORTCUT_MAPPINGS_PRIORITY = 8; @@ -29,6 +38,10 @@ export default function Priority() { selectedPriorityConvoAtom ); + const [hasMicPermissions, sethasMicPermissions] = useRecoilState( + hasMicPermissionsAtom + ); + // set keyboard shortcuts for 1->8, but only if this component is shown, and not in stuff like // convo view useEffect(() => { @@ -45,6 +58,32 @@ export default function Priority() { setmapShortcutsToConvoId(newMap); }, [priorityConvos]); + // checking for permissions for recording + useEffect(() => { + try { + // won't work in https!!! + navigator.mediaDevices + .getUserMedia({ audio: true }) + .then((stream) => { + // stop playing anything + // stopBothVideoAndAudio(stream); + + console.log("Permission Granted"); + sethasMicPermissions(true); + }) + .catch((e) => { + console.log("Permission Denied"); + toast.error( + "Please make sure that you have connected a microphone and given permissions." + ); + sethasMicPermissions(false); + }); + } catch (error) { + console.log(error); + toast.error("something went wrong"); + } + }, []); + const selectingPriorityConvoHandler = (event) => { const key = event.key; @@ -66,13 +105,69 @@ export default function Priority() { ignoreTags: ["input", "select", "textarea"], }); + const [recordingToastId, setRecordingToastId] = useState(""); + const [isRecording, setIsRecording] = useRecoilState(isRecordingAtom); + const startRecording = () => { - toast.loading("speaking to Patels"); + // check if there is a person selected + + // check that we have mic permissions + if (!hasMicPermissions) { + toast.error( + "Please make sure that you have connected a microphone and given permissions." + ); + + return; + } + + // check that we are not in flow state + + // start recording + recorder + .start() + .then(() => { + // toast.success("started recording"); + console.log("recording started"); + + setIsRecording(true); + }) + .catch((e) => + toast.error("there was a problem in starting your recording") + ); + + const toastId = toast.loading("speaking to Patels"); + setRecordingToastId(toastId); }; const stopRecording = () => { console.log("stop recording"); - toast.dismiss(); + toast.remove(recordingToastId); + + if (!isRecording) { + return; + } + + setIsRecording(false); + + recorder + .stop() + .getMp3() + .then(([buffer, blob]) => { + const blobURL = URL.createObjectURL(blob); + + 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(); + }) + .catch((error) => { + console.log(error); + toast.error("problem in sending audio clip"); + }); }; const keyMap: KeyMap = { diff --git a/packages/web/recoil/MainRecoilDataHandler.tsx b/packages/web/recoil/MainRecoilDataHandler.tsx index 691a64c..5026b1c 100644 --- a/packages/web/recoil/MainRecoilDataHandler.tsx +++ b/packages/web/recoil/MainRecoilDataHandler.tsx @@ -131,10 +131,10 @@ export default function MainRecoilDataHandler() { allUsersToCache = [...allUsersToCache, ...currconvo.activeMembers]; }); - console.log( - "going to try caching a bunch of users...maybe some duplicates", - allUsersToCache - ); + // console.log( + // "going to try caching a bunch of users...maybe some duplicates", + // allUsersToCache + // ); // if this userId is in the contacts map, then cool // otherwise fetch with userService @@ -145,12 +145,11 @@ export default function MainRecoilDataHandler() { relContacts.get(oUser) instanceof User ) { // do nothing - - console.log("user already cached, no need to re-cache"); + // console.log("user already cached, no need to re-cache"); } else { // otherwise, fetch document from firestore and then set the cache const retrievedUser = await userService.getUser(oUser); - console.log("fetching user to add to cache"); + // console.log("fetching user to add to cache"); if (retrievedUser) { setRelContacts(new Map(relContacts.set(oUser, retrievedUser))); @@ -165,7 +164,7 @@ export default function MainRecoilDataHandler() { newMap.set(currconvo.id, currconvo); }); - console.log("updated convos: ", newMap); + // console.log("updated convos: ", newMap); return newMap; }); diff --git a/packages/web/recoil/main.tsx b/packages/web/recoil/main.tsx index 9fd1cea..a2fe1a1 100644 --- a/packages/web/recoil/main.tsx +++ b/packages/web/recoil/main.tsx @@ -43,6 +43,9 @@ export enum RecoilActions { COUNT_DEFAULT_CONVOS_SELECTOR = "COUNT_DEFAULT_CONVOS_SELECTOR", COUNT_NAVIGATION_ITEMS = "COUNT_NAVIGATION_ITEMS", + + IS_RECORDING_ATOM = "IS_RECORDING_ATOM", + HAS_MIC_PERMISSIONS = "HAS_MIC_PERMISSIONS", } export const nirvanaUserDataAtom = atom({ @@ -378,8 +381,8 @@ export const allRelevantContactsAtom = atom>({ // and return their full information...either get from cache if there or fetch from database if not and update cache // RECORDING, SHORTCUTS, PLAYING, MIC, HEADPHONES, etc. -export const isRecording = atom({ - key: "haha", +export const isRecordingAtom = atom({ + key: RecoilActions.IS_RECORDING_ATOM, default: false, }); @@ -388,3 +391,8 @@ export const selectedPriorityConvoAtom = atom({ key: RecoilActions.SELECTED_CONVERSATION_ATOM, default: null, }); + +export const hasMicPermissionsAtom = atom({ + key: RecoilActions.HAS_MIC_PERMISSIONS, + default: false, +});