1
0

Started implementing draggable video feeds

Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
James Ketrenos 2022-03-24 13:28:22 -07:00
parent 2e48ab04e2
commit 33144cb267
5 changed files with 103 additions and 33 deletions

View File

@ -21,6 +21,8 @@
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-moment": "^1.1.1",
"react-movable": "^3.0.4",
"react-moveable": "^0.31.1",
"react-router-dom": "^6.2.1",
"react-scripts": "5.0.0",
"socket.io-client": "^4.4.1",

View File

@ -1,23 +1,44 @@
.MediaControlSpacer {
display: flex;
width: 5rem;
min-width: 5rem;
height: 3.75rem;
min-height: 3.75rem;
background-color: #444;
border-radius: 0.25rem;
}
.MediaControl {
display: flex;
position: relative;
position: fixed;
flex-direction: row;
justify-content: flex-end;
align-items: center;
width: 5rem;
height: 3.75rem;
min-width: 5rem;
min-height: 3.75rem;
z-index: 50000;
}
.MediaControl .Video {
position: relative;
width: 100%;
height: 100%;
/*
width: 5rem;
height: 3.75rem;
/*
max-width: 5rem;
max-height: 3.75rem;
*/
background-color: #444;
border-radius: 0.25rem;
border: 1px solid black;
}
.MediaControl.Medium .Video {
position: relative;
/*
display: flex;
width: 11.5em;
height: 8.625em;
@ -67,4 +88,13 @@
.MediaControl .Controls > div:hover {
background-color: #d0d0d0;
}
.moveable-control-box {
border: none;
--moveable-color: unset !important;
}
.moveable-control-box .moveable-direction {
border: none !important;
}

View File

@ -1,5 +1,7 @@
import React, { useState, useEffect, useRef, useCallback,
useContext } from "react";
import Moveable from "react-moveable";
import "./MediaControl.css";
import VolumeOff from '@mui/icons-material/VolumeOff';
@ -494,7 +496,7 @@ const MediaAgent = ({setPeers}) => {
});
canvas.getContext('2d').fillRect(0, 0, width, height);
const stream = canvas.captureStream();
return Object.assign(stream.getVideoTracks()[0], {
return Object.assign(stream.getVideoTracks()[1], {
enabled: true
});
}
@ -563,7 +565,15 @@ const MediaControl = ({isSelf, peer, className}) => {
const [media, setMedia] = useState(undefined);
const [muted, setMuted] = useState(undefined);
const [videoOn, setVideoOn] = useState(undefined);
const [target, setTarget] = useState();
const [frame, setFrame] = useState({
translate: [0, 0],
});
useEffect(() => {
setTarget(document.querySelectorAll(".MediaControl")[0]);
}, []);
/* local state is used to trigger re-renders, and the global
* state is kept up to date in the peers object so re-assignment
* of sessions doesn't kill the peer or change the mute/video states */
@ -625,27 +635,62 @@ const MediaControl = ({isSelf, peer, className}) => {
colorAudio = (isValid && media.hasAudio) ? 'primary' : 'disabled',
colorVideo = (isValid && media.hasVideo) ? 'primary' : 'disabled';
return <div className={`MediaControl ${className}`}>
<div className="Controls" >
{ isSelf && <div onClick={toggleMute}>
{ muted && <MicOff color={colorAudio}/> }
{!muted && <Mic color={colorAudio}/> }
</div> }
{ !isSelf && <div onClick={toggleMute}>
{muted && <VolumeOff color={colorAudio}/> }
{!muted && <VolumeUp color={colorAudio}/> }
</div> }
<div onClick={toggleVideo}>
{ !videoOn && <VideocamOff color={colorVideo}/> }
{videoOn && <Videocam color={colorVideo}/> }
return <>
<div className="MediaControlSpacer"/>
<div className={`MediaControl ${className}`}>
<div className="Controls" >
{ isSelf && <div onClick={toggleMute}>
{ muted && <MicOff color={colorAudio}/> }
{!muted && <Mic color={colorAudio}/> }
</div> }
{ !isSelf && <div onClick={toggleMute}>
{muted && <VolumeOff color={colorAudio}/> }
{!muted && <VolumeUp color={colorAudio}/> }
</div> }
<div onClick={toggleVideo}>
{ !videoOn && <VideocamOff color={colorVideo}/> }
{videoOn && <Videocam color={colorVideo}/> }
</div>
</div>
{ isValid && <>
<Moveable
draggable={true}
target={target}
resizable={true}
keepRatio={true}
throttleResize={0}
hideDefaultLines={false}
edge={true}
zoom={1}
origin={false}
onDragStart={e => {
e.set(frame.translate);
}}
onDrag={e => {
frame.translate = e.beforeTranslate;
}}
onResizeStart={e => {
e.setOrigin(["%", "%"]);
e.dragStart && e.dragStart.set(frame.translate);
}}
onResize={e => {
const { translate, rotate, transformOrigin } = frame;
e.target.style.width = `${e.width}px`;
e.target.style.height = `${e.height}px`;
e.target.style.transform = `translate(${translate[0]}px, ${translate[1]}px)`;
}}
onRender={e => {
const { translate, rotate, transformOrigin } = frame;
//e.target.style.transformOrigin = transformOrigin;
e.target.style.transform = `translate(${translate[0]}px, ${translate[1]}px)`;
}}
/><Video className="Video"
autoPlay='autoplay'
{...media.attributes}/>
</> }
{ !isValid && <video className="Video"></video> }
</div>
{ isValid && <Video className="Video"
autoPlay='autoplay'
{...media.attributes}/>
}
{ !isValid && <video className="Video"></video> }
</div>;
</>;
};
export { MediaControl, MediaAgent };

View File

@ -48,6 +48,7 @@
}
.PlayerList .Unselected > div:nth-child(2) > div {
justify-content: flex-end;
display: flex;
flex-direction: column;
align-items: center;
@ -99,6 +100,7 @@
border-radius: 0.25em;
min-width: 11em;
padding: 0 1px;
justify-content: flex-end;
}
.PlayerList .PlayerSelector .PlayerEntry > div:first-child {
@ -114,16 +116,6 @@
cursor: pointer;
}
.PlayerList .PlayerEntry[data-selected=true] {
}
.PlayerList .PlayerSelector .PlayerEntry .MediaControl {
display: flex;
justify-self: flex-end;
align-self: center;
}
.PlayerList .Players .PlayerToggle {
min-width: 5em;
display: inline-flex;

View File

@ -18,6 +18,7 @@ html {
}
body {
position: relative;
height: 100%;
width: 100%;
margin: 0;