allowing showing video in footer controls

This commit is contained in:
talksik
2022-06-28 10:13:26 -05:00
parent 2868c2356c
commit 1c8ec5f6bc
2 changed files with 71 additions and 16 deletions
@@ -63,6 +63,12 @@ function useSocketFire() {
return { handleConnectToLine, handleTuneIntoLine, handleUntuneFromLine }; return { handleConnectToLine, handleTuneIntoLine, handleUntuneFromLine };
} }
const videoConstraints = {
frameRate: 15,
width: { max: 720, ideal: 720, min: 100 },
height: { max: 720, ideal: 720, min: 100 },
};
interface IConversationContext { interface IConversationContext {
conversationMap: ConversationMap; conversationMap: ConversationMap;
@@ -78,6 +84,10 @@ interface IConversationContext {
handleEscape?: () => void; handleEscape?: () => void;
updateConversationPriority?: (conversationId: string, newState: MemberState) => Promise<void>; updateConversationPriority?: (conversationId: string, newState: MemberState) => Promise<void>;
userLocalStream?: MediaStream;
handleCastVideo?: () => void;
handleStopVideo?: () => void;
} }
const ConversationContext = React.createContext<IConversationContext>({ const ConversationContext = React.createContext<IConversationContext>({
@@ -412,6 +422,7 @@ export function ConversationProvider({ children }: { children: React.ReactNode }
return [priorityConversations, inboxConversations]; return [priorityConversations, inboxConversations];
}, [conversationMap, user]); }, [conversationMap, user]);
// move from priority to inbox and vice versa
const updateConversationPriorityHandler = useCallback( const updateConversationPriorityHandler = useCallback(
async (conversationId: string, newState: MemberState) => { async (conversationId: string, newState: MemberState) => {
try { try {
@@ -435,6 +446,22 @@ export function ConversationProvider({ children }: { children: React.ReactNode }
[setConversationMap, user], [setConversationMap, user],
); );
const [userLocalStream, setUserLocalStream] = useState<MediaStream>();
const handleCastVideo = useCallback(() => {
// create a new stream
// if there's a selected conversation, then send it to that conversation
navigator.mediaDevices
.getUserMedia({ video: videoConstraints, audio: false })
.then((userStream: MediaStream) => {
setUserLocalStream(userStream);
})
.catch((error) => toast.error('problem getting video'));
}, [setUserLocalStream]);
const handleStopVideo = useCallback(() => {
setUserLocalStream(undefined);
}, [setUserLocalStream]);
const handleEscape = useCallback(() => { const handleEscape = useCallback(() => {
selectConversation(undefined); selectConversation(undefined);
}, [selectConversation]); }, [selectConversation]);
@@ -473,6 +500,9 @@ export function ConversationProvider({ children }: { children: React.ReactNode }
inboxConversations: masterConversations[1], inboxConversations: masterConversations[1],
handleEscape, handleEscape,
updateConversationPriority: updateConversationPriorityHandler, updateConversationPriority: updateConversationPriorityHandler,
userLocalStream,
handleStopVideo,
handleCastVideo,
}} }}
> >
{children} {children}
@@ -493,12 +523,6 @@ export default function useConversations() {
return React.useContext(ConversationContext); return React.useContext(ConversationContext);
} }
const videoConstraints = {
frameRate: 15,
width: { max: 100 },
height: { max: 200 },
};
const iceServers = [ const iceServers = [
// { urls: 'stun:stun.l.google.com:19302' }, // { urls: 'stun:stun.l.google.com:19302' },
// { urls: 'stun:stun.l.google.com:19302' }, // { urls: 'stun:stun.l.google.com:19302' },
+41 -10
View File
@@ -30,7 +30,7 @@ import {
FiZap, FiZap,
FiZapOff, FiZapOff,
} from 'react-icons/fi'; } from 'react-icons/fi';
import React, { useCallback, useMemo, useState } from 'react'; import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { MasterConversation } from '../util/types'; import { MasterConversation } from '../util/types';
import { MdOutlineRecordVoiceOver } from 'react-icons/md'; import { MdOutlineRecordVoiceOver } from 'react-icons/md';
@@ -46,7 +46,13 @@ import useZen from '../providers/ZenProvider';
export default function FooterControls() { export default function FooterControls() {
const { handleFlowState } = useZen(); const { handleFlowState } = useZen();
const { selectedConversation, priorityConversations } = useConversations(); const {
selectedConversation,
priorityConversations,
userLocalStream,
handleCastVideo,
handleStopVideo,
} = useConversations();
const { user, handleLogout } = useAuth(); const { user, handleLogout } = useAuth();
const { handleToggleDesktopMode, desktopMode } = useElectron(); const { handleToggleDesktopMode, desktopMode } = useElectron();
@@ -77,8 +83,16 @@ export default function FooterControls() {
const [isVideoOn, setIsVideoOn] = useState<boolean>(false); const [isVideoOn, setIsVideoOn] = useState<boolean>(false);
const handleToggleVideo = useCallback(() => { const handleToggleVideo = useCallback(() => {
setIsVideoOn((prevVal) => !prevVal); setIsVideoOn((prevVal) => {
}, [setIsVideoOn]); if (!prevVal) {
handleCastVideo();
} else {
handleStopVideo();
}
return !prevVal;
});
}, [setIsVideoOn, handleCastVideo, handleStopVideo]);
const handleCloseUserSettings = useCallback(() => { const handleCloseUserSettings = useCallback(() => {
setOpenUserSettings(false); setOpenUserSettings(false);
@@ -96,6 +110,13 @@ export default function FooterControls() {
return false; return false;
}, [selectedConversation, priorityConversations]); }, [selectedConversation, priorityConversations]);
const localVideoRef = useRef<HTMLVideoElement>(null);
useEffect(() => {
if (localVideoRef?.current && userLocalStream) {
localVideoRef.current.srcObject = userLocalStream;
}
}, [localVideoRef, userLocalStream]);
return ( return (
<Box <Box
sx={{ sx={{
@@ -162,7 +183,11 @@ export default function FooterControls() {
aria-haspopup="true" aria-haspopup="true"
aria-expanded={open ? 'true' : undefined} aria-expanded={open ? 'true' : undefined}
> >
<Avatar alt={user.givenName} src={user.picture} /> {isVideoOn ? (
<Box height={60} width={40} ref={localVideoRef} component={'video'} autoPlay />
) : (
<Avatar alt={user.givenName} src={user.picture} />
)}
</IconButton> </IconButton>
<Divider orientation="horizontal" flexItem /> <Divider orientation="horizontal" flexItem />
@@ -188,7 +213,8 @@ function OverlayConversation({
}) { }) {
const { user } = useAuth(); const { user } = useAuth();
const { selectConversation, handleEscape, updateConversationPriority } = useConversations(); const { selectConversation, handleEscape, updateConversationPriority, userLocalStream } =
useConversations();
const handleSelectConversation = useCallback(() => { const handleSelectConversation = useCallback(() => {
if (!isSelected) { if (!isSelected) {
@@ -215,6 +241,10 @@ function OverlayConversation({
updateConversationPriority(masterConversation._id.toString(), 'priority'); updateConversationPriority(masterConversation._id.toString(), 'priority');
}, [updateConversationPriority, isPriority, masterConversation._id]); }, [updateConversationPriority, isPriority, masterConversation._id]);
const userVideoRef = useRef<HTMLVideoElement>(null);
useEffect(() => {}, []);
return ( return (
<Stack <Stack
direction={'column'} direction={'column'}
@@ -264,8 +294,8 @@ function OverlayConversation({
}} }}
max={3} max={3}
> >
{masterConversation.members?.map( {masterConversation.members?.map((conversationUser, index) => {
(conversationUser, index) => return (
(conversationUser._id.toString() !== user._id.toString() || isSelected) && ( (conversationUser._id.toString() !== user._id.toString() || isSelected) && (
<Avatar <Avatar
key={`${masterConversation._id.toString()}-${conversationUser._id.toString()}-convoIcon`} key={`${masterConversation._id.toString()}-${conversationUser._id.toString()}-convoIcon`}
@@ -279,8 +309,9 @@ function OverlayConversation({
: '20%', : '20%',
}} }}
/> />
), )
)} );
})}
</AvatarGroup> </AvatarGroup>
{isSelected && ( {isSelected && (