From 33144cb2673a674611dc4fc63bbe14c4b73f1a1e Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Thu, 24 Mar 2022 13:28:22 -0700 Subject: [PATCH] Started implementing draggable video feeds Signed-off-by: James Ketrenos --- client/package.json | 2 + client/src/MediaControl.css | 34 ++++++++++++++- client/src/MediaControl.js | 87 ++++++++++++++++++++++++++++--------- client/src/PlayerList.css | 12 +---- client/src/index.css | 1 + 5 files changed, 103 insertions(+), 33 deletions(-) diff --git a/client/package.json b/client/package.json index 0fc2300..9eaa7d1 100644 --- a/client/package.json +++ b/client/package.json @@ -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", diff --git a/client/src/MediaControl.css b/client/src/MediaControl.css index ad28b63..d365bf7 100644 --- a/client/src/MediaControl.css +++ b/client/src/MediaControl.css @@ -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; } \ No newline at end of file diff --git a/client/src/MediaControl.js b/client/src/MediaControl.js index ecd1919..e702950 100644 --- a/client/src/MediaControl.js +++ b/client/src/MediaControl.js @@ -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
-
- { isSelf &&
- { muted && } - {!muted && } -
} - { !isSelf &&
- {muted && } - {!muted && } -
} -
- { !videoOn && } - {videoOn && } + return <> +
+
+
+ { isSelf &&
+ { muted && } + {!muted && } +
} + { !isSelf &&
+ {muted && } + {!muted && } +
} +
+ { !videoOn && } + {videoOn && } +
+ { isValid && <> + { + 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)`; + }} + />
- { isValid &&
; + ; }; export { MediaControl, MediaAgent }; diff --git a/client/src/PlayerList.css b/client/src/PlayerList.css index 74f1e98..adee83f 100644 --- a/client/src/PlayerList.css +++ b/client/src/PlayerList.css @@ -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; diff --git a/client/src/index.css b/client/src/index.css index a6ac626..ccf904b 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -18,6 +18,7 @@ html { } body { + position: relative; height: 100%; width: 100%; margin: 0;