feat(frontend): assist func

This commit is contained in:
ShiKhu 2021-06-29 23:00:18 +02:00
parent 0c78d83774
commit 70159bbeb6
6 changed files with 71 additions and 89 deletions

View file

@ -1,49 +1,12 @@
import React, { useEffect, useRef } from 'react';
import { connect } from 'react-redux';
import { findDOMNode } from 'react-dom';
import {
PlayerProvider,
attach as attachPlayer,
init as initPlayer,
clean as cleanPlayer,
callPeer,
// scale
} from 'App/player';
import ChatWindow from './ChatWindow/ChatWindow'
//import ScreenSharing from './ScreenSharing/ScreenSharing'
import React from 'react';
import ChatWindow from './ChatWindow/ChatWindow';
function Assist({ session, jwt }) {
const screeRef = useRef<HTMLDivElement>(null);
useEffect(() => {
initPlayer(session, jwt);
return () => cleanPlayer()
}, [ session.sessionId ]);
useEffect(() => {
if (screeRef.current) {
attachPlayer(findDOMNode(screeRef.current));
}
}, [ ])
export default function Assist() {
return (
<div className="absolute">
{/* <div ref={screeRef}
// Just for testing TODO: flexible layout.
// It should consider itself as empty but take maximum of the space available
// Screen will adapt automatically.
style={{height: "300px", width:"600px" }}
className="relative overflow-hidden bg-gray-lightest"
/> */}
<ChatWindow call={ callPeer } />
<ChatWindow />
</div>
)
}
export default connect(state => ({
// session: { // Testing mock. Should be retrieved from redux
// // startedAt: 1624314191394,
// live: true,
// // sessionId: "4870254843916045",
// },
jwt: state.get('jwt'),
}))(Assist);

View file

@ -1,41 +1,31 @@
import React, { useState, useEffect } from 'react';
import { IconButton } from 'UI';
//import { IconButton } from 'UI';
import VideoContainer from '../components/VideoContainer';
import stl from './chatWindow.css';
import { callPeer } from 'App/player';
interface Props {
call: (oStream: MediaStream, cb: (iStream: MediaStream)=>void)=>void
}
// export interface Props {
// call: (oStream: MediaStream, cb: (iStream: MediaStream)=>void)=>void
// }
function ChatWindow({ call }: Props) {
function ChatWindow() {
const [ inputStream, setInputStream ] = useState<MediaStream | null>(null);
const [ outputStream, setOutputStream ] = useState<MediaStream | null>(null);
useEffect(() => {
startOutputStream()
callPeer()
}, [])
const startOutputStream = () => {
navigator.mediaDevices.getUserMedia({video:true, audio:true})
.then(oStream => {
setOutputStream(oStream);
call(oStream, setInputStream); // Returns false when unable to connect.
callPeer(oStream, setInputStream, () => {
console.log('endd')
outputStream?.getTracks().forEach(t => t.stop());
//inputStream?.
}); // Returns false when unable to connect.
// TODO: handle calling state
})
.catch(console.log) // TODO: handle error in ui
}
}, [])
// const onCallClick = () => {
// navigator.mediaDevices.getUserMedia({video:true, audio:true})
// .then(oStream => {
// setOutputStream(oStream);
// call(oStream, setInputStream); // Returns false when unable to connect.
// // TODO: handle calling state
// })
// .catch(console.log) // TODO: handle error in ui
// }
return (
<div className="fixed border radius bg-white z-50 shadow-xl mt-16">
<div className="p-2">

View file

@ -2,13 +2,13 @@ import React, { useState, useEffect, useRef } from 'react'
import { Button, Icon } from 'UI'
interface Props {
stream: MediaProvider | null
stream: MediaStream | null
muted?: boolean
}
function VideoContainer({ stream, muted = false }: Props) {
const [muteAudio, setMuteAudio] = useState(false)
const [muteVideo, setMuteVideo] = useState(false)
const [audioEnabled, setAudioEnabled] = useState(true)
const [videoEnabled, setVideoEnabled] = useState(true)
const ref = useRef<HTMLVideoElement>(null);
useEffect(() => {
@ -18,13 +18,17 @@ function VideoContainer({ stream, muted = false }: Props) {
}, [ ref.current, stream ])
const toggleAudio = () => {
// stream.getAudioTracks().forEach(track => track.enabled = !track.enabled);
setMuteAudio(!muteAudio)
if (!stream) { return; }
const aEn = !audioEnabled
stream.getAudioTracks().forEach(track => track.enabled = aEn);
setAudioEnabled(aEn);
}
const toggleVideo = () => {
// stream.getVideoTracks().forEach(track => track.enabled = !track.enabled);
setMuteVideo(!muteVideo)
if (!stream) { return; }
const vEn = !videoEnabled;
stream.getVideoTracks().forEach(track => track.enabled = vEn);
setVideoEnabled(vEn)
}
return (
@ -33,11 +37,11 @@ function VideoContainer({ stream, muted = false }: Props) {
<video autoPlay ref={ ref } muted={ muted } />
<div className="flex items-center absolute w-full justify-center bottom-0 bg-gray-lightest">
<Button plain size="small" onClick={toggleAudio}>
<Icon name={muteAudio ? 'mic-mute' : 'mic'} size="16" />
<Icon name={audioEnabled ? 'mic' : 'mic-mute'} size="16" />
</Button>
<Button plain size="small" onClick={toggleVideo}>
<Icon name={ muteVideo ? 'camera-video-off' : 'camera-video' } size="16" />
<Icon name={ videoEnabled ? 'camera-video' : 'camera-video-off' } size="16" />
</Button>
</div>
</div>

View file

@ -18,7 +18,7 @@ const ScreenWrapper = withOverlay()(React.memo(() => <div className={ stl.screen
loading: state.messagesLoading,
disconnected: state.disconnected,
disabled: state.cssLoading || state.messagesLoading || state.inspectorMode,
inspectorMode: state.inspectorMode,
removeOverlay: state.inspectorMode || state.live,
completed: state.completed,
autoplay: state.autoplay
}))
@ -96,7 +96,7 @@ export default class Player extends React.PureComponent {
className,
playing,
disabled,
inspectorMode,
removeOverlay,
bottomBlockIsActive,
loading,
disconnected,
@ -125,7 +125,7 @@ export default class Player extends React.PureComponent {
// />
}
<div className="relative flex-1">
{ !inspectorMode &&
{ !removeOverlay &&
<div
className={ stl.overlay }
onClick={ disabled ? null : this.togglePlay }

View file

@ -139,17 +139,30 @@ export default class MessageDistributor extends StatedScreen {
}
}
private getPeerID(): string {
return `${this.session.projectKey}-${this.session.sessionId}`
}
private peer: Peer | null = null;
private connectToPeer() {
this.setMessagesLoading(true);
import('peerjs').then(({ default: Peer }) => {
const peer = new Peer();
// @ts-ignore
console.log(new URL(window.ENV.API_EDP).host)
const peer = new Peer({
// @ts-ignore
host: new URL(window.ENV.API_EDP).host,
path: '/assist',
port: 80,
});
this.peer = peer;
peer.on("open", me => {
console.log("peer opened", me);
const id = `3sWXSsqHgSKnEO5YkNJK-${this.session.sessionId}`;
const id = this.getPeerID();
console.log("trying to connect to", id)
const conn = peer.connect(id);
console.log("Peer ", peer)
conn.on('open', () => {
this.setMessagesLoading(false);
let i = 0;
@ -177,22 +190,33 @@ export default class MessageDistributor extends StatedScreen {
});
}
callPeer(localStream: MediaStream, cb: (s: MediaStream)=>void): boolean {
if (!this.peer) { return false; }
const conn = this.peer.connections[`3sWXSsqHgSKnEO5YkNJK-${this.session.sessionId}`]?.[0];
if (!conn || !conn.open) { return false; } // Conn not established
callPeer(localStream: MediaStream, onStream: (s: MediaStream)=>void, onClose: () => void, onRefuse?: ()=> void): ()=>void {
if (!this.peer) { return Function; }
const conn = this.peer.connections[this.getPeerID()]?.[0];
if (!conn || !conn.open) { return Function; } // Conn not established
const call = this.peer.call(conn.peer, localStream);
console.log('calling...')
// on refuse?
call.on('stream', function(stream) {
cb(stream);
});
call.on('stream', onStream);
call.on("close", onClose);
call.on("error", onClose)
return () => call.close();
}
requestMouse(): ()=>void {
if (!this.peer) { return Function; }
const conn = this.peer.connections[this.getPeerID()]?.[0];
if (!conn || !conn.open) { return Function; }
const onMouseMove = (e) => {
// @ts-ignore
const data = this._getInternalCoordinates(e)
conn.send({ x: Math.round(data.x), y: Math.round(data.y) }); // debounce?
}
//@ts-ignore
this.document?.
addEventListener("mousemove", ({ x, y }) => {
conn.send([ x, y ]); // debounce?
});
return true;
this.overlay.addEventListener("mousemove", onMouseMove);
//@ts-ignore
return () => this.overlay.removeEventListener("mousemove", onMouseMove);
}
@ -419,7 +443,6 @@ export default class MessageDistributor extends StatedScreen {
}
break;
case "set_viewport_size":
console.log("setvvs", msg)
this.resizeManager.add(msg);
break;
case "mouse_move":

View file

@ -26,6 +26,8 @@ function hashString(s: string): number {
export default Record({
sessionId: '',
siteId: '',
projectKey: '',
peerId: '',
live: true,
startedAt: 0,
duration: 0,