somewhat of a queue working and also changing to a nicer map object for the store
This commit is contained in:
@@ -15,17 +15,7 @@ import { useEffect, useState } from "react";
|
|||||||
import { toast } from "react-hot-toast";
|
import { toast } from "react-hot-toast";
|
||||||
import { TeamMemberRole, TeamMemberStatus } from "../../models/teamMember";
|
import { TeamMemberRole, TeamMemberStatus } from "../../models/teamMember";
|
||||||
import UserService from "../../services/userService";
|
import UserService from "../../services/userService";
|
||||||
import {
|
import { getFirestore } from "firebase/firestore";
|
||||||
collection,
|
|
||||||
doc,
|
|
||||||
DocumentSnapshot,
|
|
||||||
getFirestore,
|
|
||||||
onSnapshot,
|
|
||||||
orderBy,
|
|
||||||
query,
|
|
||||||
Unsubscribe,
|
|
||||||
where,
|
|
||||||
} from "firebase/firestore";
|
|
||||||
import { Collections } from "../../services/collections";
|
import { Collections } from "../../services/collections";
|
||||||
import { KeyCode } from "../../globals/keycode";
|
import { KeyCode } from "../../globals/keycode";
|
||||||
import { Tooltip } from "antd";
|
import { Tooltip } from "antd";
|
||||||
@@ -107,8 +97,8 @@ export default function TeamVoiceLine() {
|
|||||||
return teamUsers.map((tmember, i) => {
|
return teamUsers.map((tmember, i) => {
|
||||||
var isMessageIncoming: boolean = false;
|
var isMessageIncoming: boolean = false;
|
||||||
if (
|
if (
|
||||||
tmember.id in messagesByTeamMate &&
|
messagesByTeamMate.has(tmember.id) &&
|
||||||
messagesByTeamMate[tmember.id][0]?.receiverUserId == currUser.uid
|
messagesByTeamMate.get(tmember.id)[0]?.receiverUserId == currUser.uid
|
||||||
) {
|
) {
|
||||||
isMessageIncoming = true;
|
isMessageIncoming = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { useAuth } from "./authContext";
|
|||||||
import { SendService } from "../services/sendService";
|
import { SendService } from "../services/sendService";
|
||||||
import { useTeamDashboardContext } from "./teamDashboardContext";
|
import { useTeamDashboardContext } from "./teamDashboardContext";
|
||||||
import isValidHttpUrl from "../helpers/urlHelper";
|
import isValidHttpUrl from "../helpers/urlHelper";
|
||||||
|
import ReactPlayer from "react-player/lazy";
|
||||||
|
|
||||||
interface KeyboardContextInterface {
|
interface KeyboardContextInterface {
|
||||||
selectedTeammate: string; // can only have one selected
|
selectedTeammate: string; // can only have one selected
|
||||||
@@ -107,6 +108,8 @@ export default function KeyboardContextProvider({ children }) {
|
|||||||
new MicRecorder({ bitRate: 128 })
|
new MicRecorder({ bitRate: 128 })
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [audioQueue, setAudioQueue] = useState<string[]>([]); // queue for the player to keep playing
|
||||||
|
|
||||||
// playing incoming messages
|
// playing incoming messages
|
||||||
const { allMessages, messagesByTeamMate } = useTeamDashboardContext();
|
const { allMessages, messagesByTeamMate } = useTeamDashboardContext();
|
||||||
|
|
||||||
@@ -126,10 +129,21 @@ export default function KeyboardContextProvider({ children }) {
|
|||||||
|
|
||||||
// start player on the bottom
|
// start player on the bottom
|
||||||
// autoplay message
|
// autoplay message
|
||||||
setPlayerSrc(allMessages[0].audioDataUrl);
|
// add to the queue
|
||||||
|
setAudioQueue((prevQueue) => [...prevQueue, allMessages[0].audioDataUrl]);
|
||||||
}
|
}
|
||||||
}, [allMessages]);
|
}, [allMessages]);
|
||||||
|
|
||||||
|
// manage audio queue
|
||||||
|
useEffect(() => {
|
||||||
|
// every time queue changes,
|
||||||
|
// setPlayerSrc as the next item if there is any
|
||||||
|
|
||||||
|
if (audioQueue && audioQueue.length > 0) {
|
||||||
|
setPlayerSrc(audioQueue[0]);
|
||||||
|
}
|
||||||
|
}, [audioQueue]);
|
||||||
|
|
||||||
const value: KeyboardContextInterface = {
|
const value: KeyboardContextInterface = {
|
||||||
selectedTeammate,
|
selectedTeammate,
|
||||||
selectTeamMember,
|
selectTeamMember,
|
||||||
@@ -281,10 +295,12 @@ export default function KeyboardContextProvider({ children }) {
|
|||||||
function onEndedPlaying(e) {
|
function onEndedPlaying(e) {
|
||||||
toast.success("finished playing");
|
toast.success("finished playing");
|
||||||
|
|
||||||
// hide the player
|
// remove from queue and the queue manager will handle the rest
|
||||||
setPlayerSrc(null);
|
setAudioQueue((prevQueue) => {
|
||||||
|
let newQueue: string[] = [...prevQueue];
|
||||||
// if there are still items in the player queue, then change the src and play the subsequent messages
|
newQueue.shift();
|
||||||
|
return newQueue;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleKeyUp = useCallback(
|
const handleKeyUp = useCallback(
|
||||||
@@ -353,7 +369,9 @@ export default function KeyboardContextProvider({ children }) {
|
|||||||
if (!audioInputDeviceId) {
|
if (!audioInputDeviceId) {
|
||||||
toast.error("No microphone selected");
|
toast.error("No microphone selected");
|
||||||
} else if (!hasRecPermit) {
|
} else if (!hasRecPermit) {
|
||||||
toast.error("You did not allow recording permission!");
|
toast.error(
|
||||||
|
"You did not allow microphone permissions in your browser!"
|
||||||
|
);
|
||||||
} else if (!selectedTeammate) {
|
} else if (!selectedTeammate) {
|
||||||
toast.error("Please select a team member or announcements first");
|
toast.error("Please select a team member or announcements first");
|
||||||
} else if (isMuted) {
|
} else if (isMuted) {
|
||||||
@@ -378,17 +396,41 @@ export default function KeyboardContextProvider({ children }) {
|
|||||||
toast.error("select a team member first to play");
|
toast.error("select a team member first to play");
|
||||||
} else {
|
} else {
|
||||||
// alright now you are good to play last message chunk in conversation with selected user
|
// alright now you are good to play last message chunk in conversation with selected user
|
||||||
// todo create last chunk by iterating until next person, and create a playlist
|
|
||||||
|
|
||||||
|
const arrayMessagesforUser: Message[] =
|
||||||
|
messagesByTeamMate.get(selectedTeammate);
|
||||||
if (
|
if (
|
||||||
selectedTeammate in messagesByTeamMate &&
|
messagesByTeamMate.has(selectedTeammate) &&
|
||||||
messagesByTeamMate[selectedTeammate] &&
|
arrayMessagesforUser &&
|
||||||
messagesByTeamMate[selectedTeammate].length > 0
|
arrayMessagesforUser.length > 0
|
||||||
) {
|
) {
|
||||||
|
var convoChunk: string[] = [];
|
||||||
console.log("playing from this cache");
|
console.log("playing from this cache");
|
||||||
|
|
||||||
console.log(messagesByTeamMate);
|
// wait for x changes, and then break adding to the queue...I want to hear the past loop of conversation maybe
|
||||||
setPlayerSrc(messagesByTeamMate[selectedTeammate][0].audioDataUrl);
|
const maxConvoChanges: number = 2;
|
||||||
|
var convoChangeCount: number = 0;
|
||||||
|
|
||||||
|
var currTalkerId = arrayMessagesforUser[0].senderUserId;
|
||||||
|
for (const audioMessage of arrayMessagesforUser) {
|
||||||
|
if (audioMessage.senderUserId != currTalkerId) {
|
||||||
|
convoChangeCount += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// heard enough of this convo
|
||||||
|
if (convoChangeCount == maxConvoChanges) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
convoChunk.push(audioMessage.audioDataUrl);
|
||||||
|
currTalkerId = audioMessage.senderUserId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reverse the chunk so that I listen to the messages in order
|
||||||
|
convoChunk.reverse();
|
||||||
|
|
||||||
|
// add convo chunk to the queue player
|
||||||
|
setAudioQueue((prevQueue) => [...prevQueue, ...convoChunk]);
|
||||||
} else {
|
} else {
|
||||||
toast("nothing to play");
|
toast("nothing to play");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ interface TeamDashboardContextInterface {
|
|||||||
|
|
||||||
user: User; // REALTIME - 1
|
user: User; // REALTIME - 1
|
||||||
|
|
||||||
messagesByTeamMate: {}; // REALTIME: string of teammate userid and array of messages - 1
|
messagesByTeamMate: Map<string, Message[]>; // REALTIME: string of teammate userid and array of messages - 1
|
||||||
allMessages: Message[]; // REALTIME: 1
|
allMessages: Message[]; // REALTIME: 1
|
||||||
|
|
||||||
teamUsers: User[]; // REALTIME teammates - n team members => n listeners
|
teamUsers: User[]; // REALTIME teammates - n team members => n listeners
|
||||||
@@ -115,7 +115,7 @@ export function TeamDashboardContextProvider({ children }) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// if you are not a member of this team, then get out of here
|
// if you are not a member of this team, then get out of here
|
||||||
// but have to check through email invite and userid
|
// but have to check through email invite and userid
|
||||||
if (
|
if (
|
||||||
returnedTeamMember &&
|
returnedTeamMember &&
|
||||||
returnedTeamMember.status == TeamMemberStatus.deleted
|
returnedTeamMember.status == TeamMemberStatus.deleted
|
||||||
@@ -224,7 +224,9 @@ export function TeamDashboardContextProvider({ children }) {
|
|||||||
const [teamUsersMap, setTeamUsersMap] = useState<{}>({});
|
const [teamUsersMap, setTeamUsersMap] = useState<{}>({});
|
||||||
|
|
||||||
const [allMessages, setAllMessages] = useState<Message[]>([]);
|
const [allMessages, setAllMessages] = useState<Message[]>([]);
|
||||||
const [messagesByTeamMate, setMessagesByTeamMate] = useState<{}>({});
|
const [messagesByTeamMate, setMessagesByTeamMate] = useState<
|
||||||
|
Map<string, Message[]>
|
||||||
|
>(new Map());
|
||||||
|
|
||||||
// SECTION: REALTIME listener for all incoming messages
|
// SECTION: REALTIME listener for all incoming messages
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -257,28 +259,29 @@ export function TeamDashboardContextProvider({ children }) {
|
|||||||
// update map of teammate to relevant messages
|
// update map of teammate to relevant messages
|
||||||
setMessagesByTeamMate((prevMap) => {
|
setMessagesByTeamMate((prevMap) => {
|
||||||
// if the map contains the teammate userid already, then cool, just unshift to that array
|
// if the map contains the teammate userid already, then cool, just unshift to that array
|
||||||
const newMap = { ...prevMap };
|
var newMap: Map<string, Message[]> = new Map(
|
||||||
if (newMessage.receiverUserId in prevMap) {
|
prevMap.set("dummy", [] as Message[])
|
||||||
// won't be in map if I am the receiver
|
);
|
||||||
newMap[newMessage.receiverUserId] = [
|
if (prevMap.has(newMessage.receiverUserId)) {
|
||||||
|
newMap.set(newMessage.receiverUserId, [
|
||||||
newMessage,
|
newMessage,
|
||||||
...prevMap[newMessage.receiverUserId],
|
...prevMap.get(newMessage.receiverUserId),
|
||||||
];
|
]);
|
||||||
} // if this is the first relevant message linked to this receiver,
|
} // if this is the first relevant message linked to this receiver,
|
||||||
//then create a new array
|
//then create a new array
|
||||||
else {
|
else {
|
||||||
newMap[newMessage.receiverUserId] = [newMessage];
|
newMap.set(newMessage.receiverUserId, [newMessage]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: if I am the receiver, still want to put it in the right conversation
|
// todo: if I am the receiver, still want to put it in the right conversation
|
||||||
if (newMessage.receiverUserId == currUser.uid) {
|
if (newMessage.receiverUserId == currUser.uid) {
|
||||||
if (newMessage.senderUserId in prevMap) {
|
if (prevMap.has(newMessage.senderUserId)) {
|
||||||
newMap[newMessage.senderUserId] = [
|
newMap.set(newMessage.senderUserId, [
|
||||||
newMessage,
|
newMessage,
|
||||||
...prevMap[newMessage.senderUserId],
|
...prevMap.get(newMessage.senderUserId),
|
||||||
];
|
]);
|
||||||
} else {
|
} else {
|
||||||
newMap[newMessage.senderUserId] = [newMessage];
|
newMap.set(newMessage.senderUserId, [newMessage]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user