feat(tracker-assist): 3.5.0 websocket-rewritten
This commit is contained in:
parent
2d252735e7
commit
a759aa84d3
5 changed files with 2211 additions and 260 deletions
1915
tracker/tracker-assist/package-lock.json
generated
1915
tracker/tracker-assist/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@openreplay/tracker-assist",
|
||||
"description": "Tracker plugin for screen assistance through the WebRTC",
|
||||
"version": "3.4.16",
|
||||
"version": "3.5.0",
|
||||
"keywords": [
|
||||
"WebRTC",
|
||||
"assistance",
|
||||
|
|
@ -15,19 +15,24 @@
|
|||
"scripts": {
|
||||
"lint": "prettier --write 'src/**/*.ts' README.md && tsc --noEmit",
|
||||
"build": "npm run build-es && npm run build-cjs",
|
||||
"build-es": "rm -Rf lib && tsc",
|
||||
"build-cjs": "rm -Rf cjs && tsc --project tsconfig-cjs.json && echo '{ \"type\": \"commonjs\" }' > cjs/package.json && replace-in-files cjs/* --string='@openreplay/tracker' --replacement='@openreplay/tracker/cjs' && replace-in-files cjs/* --string='/lib/' --replacement='/'",
|
||||
"build-es": "rm -Rf lib && tsc && npm run replace-versions",
|
||||
"build-cjs": "rm -Rf cjs && tsc --project tsconfig-cjs.json && echo '{ \"type\": \"commonjs\" }' > cjs/package.json && npm run replace-paths && npm run replace-versions",
|
||||
"replace-paths": "replace-in-files cjs/* --string='@openreplay/tracker' --replacement='@openreplay/tracker/cjs' && replace-in-files cjs/* --string='/lib/' --replacement='/'",
|
||||
"replace-versions": "npm run replace-pkg-version && npm run replace-req-version",
|
||||
"replace-pkg-version": "replace-in-files lib/* cjs/* --string='PACKAGE_VERSION' --replacement=$npm_package_version",
|
||||
"replace-req-version": "replace-in-files lib/* cjs/* --string='REQUIRED_TRACKER_VERSION' --replacement='3.5.0'",
|
||||
"prepublishOnly": "npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"npm-dragndrop": "^1.2.0",
|
||||
"peerjs": "^1.3.2"
|
||||
"peerjs": "^1.3.2",
|
||||
"socket.io-client": "^4.4.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@openreplay/tracker": "^3.4.8"
|
||||
"@openreplay/tracker": "^3.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@openreplay/tracker": "^3.4.8",
|
||||
"@openreplay/tracker": "file:../tracker",
|
||||
"prettier": "^1.18.2",
|
||||
"replace-in-files-cli": "^1.0.0",
|
||||
"typescript": "^4.6.0-dev.20211126"
|
||||
|
|
|
|||
290
tracker/tracker-assist/src/Assist.ts
Normal file
290
tracker/tracker-assist/src/Assist.ts
Normal file
|
|
@ -0,0 +1,290 @@
|
|||
import type { Socket } from 'socket.io-client';
|
||||
import io from 'socket.io-client';
|
||||
import Peer from 'peerjs';
|
||||
import { App } from '@openreplay/tracker';
|
||||
|
||||
import Mouse from './Mouse.js';
|
||||
import CallWindow from './CallWindow.js';
|
||||
import ConfirmWindow from './ConfirmWindow.js';
|
||||
import RequestLocalStream from './LocalStream.js';
|
||||
|
||||
|
||||
//@ts-ignore peerjs hack for webpack5 (?!) TODO: ES/node modules;
|
||||
Peer = Peer.default || Peer;
|
||||
|
||||
export interface Options {
|
||||
onAgentConnect: () => ((()=>{}) | void),
|
||||
onCallStart: () => ((()=>{}) | void),
|
||||
confirmText: string,
|
||||
confirmStyle: Object, // Styles object
|
||||
session_calling_peer_key: string,
|
||||
config: RTCConfiguration,
|
||||
}
|
||||
|
||||
|
||||
enum CallingState {
|
||||
Requesting,
|
||||
True,
|
||||
False,
|
||||
};
|
||||
|
||||
|
||||
type Agent = {
|
||||
onDisconnect: ((()=>{}) | void), // TODO: better types here
|
||||
name?: string
|
||||
//
|
||||
}
|
||||
|
||||
export default class Assist {
|
||||
readonly version = "PACKAGE_VERSION"
|
||||
|
||||
private socket: Socket | null = null
|
||||
private peer: Peer | null = null
|
||||
private assistDemandedRestart: boolean = false
|
||||
private callingState: CallingState = CallingState.False
|
||||
|
||||
private agents: Record<string, Agent> = {}
|
||||
constructor(
|
||||
private readonly app: App,
|
||||
private readonly options: Options,
|
||||
private readonly noSecureMode: boolean = false) {
|
||||
app.attachStartCallback(() => {
|
||||
if (this.assistDemandedRestart) { return; }
|
||||
this.onStart()
|
||||
})
|
||||
app.attachCommitCallback((messages) => {
|
||||
if (this.socket && this.agentsConnected) {
|
||||
// @ts-ignore No need in statistics messages. TODO proper filter
|
||||
if (messages.length === 2 && messages[0]._id === 0 && messages[1]._id === 49) { return }
|
||||
this.socket.emit("messages", messages)
|
||||
}
|
||||
})
|
||||
app.attachStopCallback(() => {
|
||||
if (this.assistDemandedRestart) { return; }
|
||||
this.clean()
|
||||
})
|
||||
}
|
||||
|
||||
private get agentsConnected(): boolean {
|
||||
return Object.keys(this.agents).length > 0
|
||||
}
|
||||
|
||||
private notifyCallEnd() {
|
||||
this.socket && this.socket.emit("call_end");
|
||||
}
|
||||
private onRemoteCallEnd = () => {}
|
||||
|
||||
private onStart() {
|
||||
const app = this.app
|
||||
const peerID = `${app.getProjectKey()}-${app.getSessionID()}`
|
||||
|
||||
// SocketIO
|
||||
const socket = this.socket = io(app.getHost(), {
|
||||
path: '/ws-assist/socket',
|
||||
query: {
|
||||
"peerId": peerID,
|
||||
"identity": "session",
|
||||
"sessionInfo": JSON.stringify(this.app.getSessionInfo()),
|
||||
}
|
||||
})
|
||||
socket.onAny((...args) => app.debug.log("Socket:", ...args))
|
||||
|
||||
socket.on("NEW_AGENT", (id: string, info) => {
|
||||
this.agents[id] = {
|
||||
onDisconnect: this.options.onAgentConnect && this.options.onAgentConnect(),
|
||||
...info, // TODO
|
||||
}
|
||||
this.assistDemandedRestart = true
|
||||
this.app.stop();
|
||||
this.app.start().then(() => { this.assistDemandedRestart = false })
|
||||
})
|
||||
socket.on("AGENTS_CONNECTED", (ids) => {
|
||||
ids.forEach(id =>{
|
||||
this.agents[id] = {
|
||||
onDisconnect: this.options.onAgentConnect && this.options.onAgentConnect(),
|
||||
}
|
||||
})
|
||||
this.assistDemandedRestart = true
|
||||
this.app.stop();
|
||||
this.app.start().then(() => { this.assistDemandedRestart = false })
|
||||
})
|
||||
|
||||
let confirmRC: ConfirmWindow | null = null
|
||||
const mouse = new Mouse() // TODO: lazy init
|
||||
let controllingAgent: string | null = null
|
||||
function releaseControl() {
|
||||
confirmRC?.remove()
|
||||
mouse.remove()
|
||||
controllingAgent = null
|
||||
}
|
||||
socket.on("request_control", (id: string) => {
|
||||
if (controllingAgent !== null) {
|
||||
socket.emit("control_rejected", id)
|
||||
return
|
||||
}
|
||||
controllingAgent = id
|
||||
confirmRC = new ConfirmWindow("Allow remote control?")
|
||||
confirmRC.mount().then(allowed => {
|
||||
if (allowed) { // TODO: per agent id
|
||||
mouse.mount()
|
||||
socket.emit("control_granted", id)
|
||||
} else {
|
||||
releaseControl()
|
||||
socket.emit("control_rejected", id)
|
||||
}
|
||||
}).catch()
|
||||
})
|
||||
socket.on("release_control", (id: string) => {
|
||||
if (controllingAgent !== id) { return }
|
||||
releaseControl()
|
||||
})
|
||||
socket.on("scroll", (id, d) => { id === controllingAgent && mouse.scroll(d) })
|
||||
socket.on("click", (id, xy) => { id === controllingAgent && mouse.click(xy) })
|
||||
socket.on("move", (id, xy) => { id === controllingAgent && mouse.move(xy) })
|
||||
|
||||
let confirmCall:ConfirmWindow | null = null
|
||||
|
||||
socket.on("AGENT_DISCONNECTED", (id) => {
|
||||
// @ts-ignore (wtf, typescript?!)
|
||||
this.agents[id] && this.agents[id].onDisconnect != null && this.agents[id].onDisconnect()
|
||||
delete this.agents[id]
|
||||
|
||||
controllingAgent === id && releaseControl()
|
||||
|
||||
// close the call also
|
||||
if (callingAgent === id) {
|
||||
confirmCall?.remove()
|
||||
this.onRemoteCallEnd()
|
||||
}
|
||||
})
|
||||
socket.on("NO_AGENT", () => {
|
||||
this.agents = {}
|
||||
})
|
||||
socket.on("call_end", () => this.onRemoteCallEnd()) // TODO: check if agent calling id
|
||||
|
||||
// TODO: fix the code
|
||||
let agentName = ""
|
||||
let callingAgent = ""
|
||||
socket.on("_agent_name",(id, name) => { agentName = name; callingAgent = id })
|
||||
|
||||
|
||||
// PeerJS call (todo: use native WebRTC)
|
||||
const peerOptions = {
|
||||
host: app.getHost(),
|
||||
path: '/assist',
|
||||
port: location.protocol === 'http:' && this.noSecureMode ? 80 : 443,
|
||||
//debug: appOptions.__debug_log ? 2 : 0, // 0 Print nothing //1 Prints only errors. / 2 Prints errors and warnings. / 3 Prints all logs.
|
||||
}
|
||||
if (this.options.config) {
|
||||
peerOptions['config'] = this.options.config
|
||||
}
|
||||
const peer = this.peer = new Peer(peerID, peerOptions);
|
||||
app.debug.log('Peer created: ', peer)
|
||||
peer.on('error', e => app.debug.warn("Peer error: ", e.type, e))
|
||||
peer.on('disconnect', () => peer.reconnect())
|
||||
peer.on('call', (call) => {
|
||||
app.debug.log("Call: ", call)
|
||||
if (this.callingState !== CallingState.False) {
|
||||
call.close()
|
||||
//this.notifyCallEnd() // TODO: strictly connect calling peer with agent socket.id
|
||||
app.debug.warn("Call closed instantly bacause line is busy. CallingState: ", this.callingState)
|
||||
return;
|
||||
}
|
||||
|
||||
const setCallingState = (newState: CallingState) => {
|
||||
if (newState === CallingState.True) {
|
||||
sessionStorage.setItem(this.options.session_calling_peer_key, call.peer);
|
||||
} else if (newState === CallingState.False) {
|
||||
sessionStorage.removeItem(this.options.session_calling_peer_key);
|
||||
}
|
||||
this.callingState = newState;
|
||||
}
|
||||
|
||||
let confirmAnswer: Promise<boolean>
|
||||
const callingPeer = sessionStorage.getItem(this.options.session_calling_peer_key)
|
||||
if (callingPeer === call.peer) {
|
||||
confirmAnswer = Promise.resolve(true)
|
||||
} else {
|
||||
setCallingState(CallingState.Requesting)
|
||||
confirmCall = new ConfirmWindow(this.options.confirmText, this.options.confirmStyle)
|
||||
confirmAnswer = confirmCall.mount()
|
||||
this.onRemoteCallEnd = () => { // if call cancelled by a caller before confirmation
|
||||
app.debug.log("Received call_end during confirm window opened")
|
||||
confirmCall?.remove()
|
||||
setCallingState(CallingState.False)
|
||||
}
|
||||
}
|
||||
|
||||
confirmAnswer.then(agreed => {
|
||||
if (!agreed) {
|
||||
call.close()
|
||||
this.notifyCallEnd()
|
||||
setCallingState(CallingState.False)
|
||||
return
|
||||
}
|
||||
|
||||
let callUI = new CallWindow()
|
||||
callUI.setAssistentName(agentName)
|
||||
|
||||
const onCallEnd = this.options.onCallStart()
|
||||
const handleCallEnd = () => {
|
||||
call.close()
|
||||
callUI.remove()
|
||||
setCallingState(CallingState.False)
|
||||
onCallEnd && onCallEnd()
|
||||
}
|
||||
const initiateCallEnd = () => {
|
||||
this.notifyCallEnd()
|
||||
handleCallEnd()
|
||||
}
|
||||
this.onRemoteCallEnd = handleCallEnd
|
||||
|
||||
call.on('error', e => {
|
||||
app.debug.warn("Call error:", e)
|
||||
initiateCallEnd()
|
||||
});
|
||||
|
||||
RequestLocalStream().then(lStream => {
|
||||
call.on('stream', function(rStream) {
|
||||
callUI.setRemoteStream(rStream);
|
||||
const onInteraction = () => { // only if hidden?
|
||||
callUI.playRemote()
|
||||
document.removeEventListener("click", onInteraction)
|
||||
}
|
||||
document.addEventListener("click", onInteraction)
|
||||
});
|
||||
|
||||
lStream.onVideoTrack(vTrack => {
|
||||
const sender = call.peerConnection.getSenders().find(s => s.track?.kind === "video")
|
||||
if (!sender) {
|
||||
app.debug.warn("No video sender found")
|
||||
return
|
||||
}
|
||||
app.debug.log("sender found:", sender)
|
||||
sender.replaceTrack(vTrack)
|
||||
})
|
||||
|
||||
callUI.setCallEndAction(initiateCallEnd)
|
||||
callUI.setLocalStream(lStream)
|
||||
call.answer(lStream.stream)
|
||||
setCallingState(CallingState.True)
|
||||
})
|
||||
.catch(e => {
|
||||
app.debug.warn("Audio mediadevice request error:", e)
|
||||
initiateCallEnd()
|
||||
});
|
||||
}).catch(); // in case of Confirm.remove() without any confirmation/decline
|
||||
});
|
||||
}
|
||||
|
||||
private clean() {
|
||||
if (this.peer) {
|
||||
this.peer.destroy()
|
||||
this.app.debug.log("Peer destroyed")
|
||||
}
|
||||
if (this.socket) {
|
||||
this.socket.disconnect()
|
||||
this.app.debug.log("Socket disconnected")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,9 +15,10 @@ export default class Mouse {
|
|||
zIndex: "999998",
|
||||
background: "radial-gradient(red, transparent)",
|
||||
});
|
||||
document.body.appendChild(this.mouse);
|
||||
|
||||
}
|
||||
|
||||
mount() {
|
||||
document.body.appendChild(this.mouse)
|
||||
window.addEventListener("scroll", this.handleWScroll)
|
||||
window.addEventListener("resize", this.resetLastScrEl)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,39 +1,9 @@
|
|||
import './_slim.js';
|
||||
import Peer from 'peerjs';
|
||||
import type { DataConnection } from 'peerjs';
|
||||
import { App, Messages } from '@openreplay/tracker';
|
||||
import type Message from '@openreplay/tracker';
|
||||
|
||||
import BufferingConnection from './BufferingConnection.js';
|
||||
import Mouse from './Mouse.js';
|
||||
import CallWindow from './CallWindow.js';
|
||||
import ConfirmWindow from './ConfirmWindow.js';
|
||||
import RequestLocalStream from './LocalStream.js';
|
||||
import type { App } from '@openreplay/tracker';
|
||||
import type { Options } from './Assist.js'
|
||||
import Assist from './Assist.js'
|
||||
|
||||
export interface Options {
|
||||
onAgentConnect: () => ((()=>{}) | void),
|
||||
onCallStart: () => ((()=>{}) | void),
|
||||
confirmText: string,
|
||||
confirmStyle: Object, // Styles object
|
||||
session_calling_peer_key: string,
|
||||
config: RTCConfiguration,
|
||||
// __messages_per_send?: number,
|
||||
}
|
||||
|
||||
enum CallingState {
|
||||
Requesting,
|
||||
True,
|
||||
False,
|
||||
};
|
||||
|
||||
//@ts-ignore peerjs hack for webpack5 (?!) TODO: ES/node modules;
|
||||
Peer = Peer.default || Peer;
|
||||
|
||||
// type IncomeMessages =
|
||||
// "call_end" |
|
||||
// { type: "agent_name", name: string } |
|
||||
// { type: "click", x: number, y: number } |
|
||||
// { x: number, y: number }
|
||||
|
||||
export default function(opts?: Partial<Options>) {
|
||||
const options: Options = Object.assign(
|
||||
|
|
@ -47,211 +17,19 @@ export default function(opts?: Partial<Options>) {
|
|||
},
|
||||
opts,
|
||||
);
|
||||
return function(app: App | null, appOptions: { __debug_log?: boolean, __DISABLE_SECURE_MODE?: boolean } = {}) {
|
||||
return function(app: App | null, appOptions: { __DISABLE_SECURE_MODE?: boolean } = {}) {
|
||||
// @ts-ignore
|
||||
if (app === null || !navigator?.mediaDevices?.getUserMedia) { // 93.04% browsers
|
||||
return;
|
||||
}
|
||||
|
||||
function log(...args) {
|
||||
// TODO: use centralised warn/log from tracker (?)
|
||||
appOptions.__debug_log && console.log("OpenReplay Assist. ", ...args)
|
||||
}
|
||||
function warn(...args) {
|
||||
appOptions.__debug_log && console.warn("OpenReplay Assist. ", ...args)
|
||||
if (!app.checkRequiredVersion || !app.checkRequiredVersion("REQUIRED_TRACKER_VERSION")) {
|
||||
console.warn("OpenReplay Assist: couldn't load. The minimum required version of @openreplay/tracker@REQUIRED_TRACKER_VERSION is not met")
|
||||
return
|
||||
}
|
||||
app.notify.log("OpenReplay Assist initializing.")
|
||||
const assist = new Assist(app, options, appOptions.__DISABLE_SECURE_MODE)
|
||||
app.debug.log(assist)
|
||||
return assist
|
||||
|
||||
let assistDemandedRestart = false
|
||||
let peer : Peer | null = null
|
||||
// This is required because internal peerjs connection list is not stable. https://peerjs.com/docs.html#peerconnections
|
||||
const openDataConnections: Record<string, BufferingConnection> = {}
|
||||
|
||||
app.addCommitCallback(function(messages) {
|
||||
Object.values(openDataConnections).forEach(buffConn => buffConn.send(messages))
|
||||
})
|
||||
|
||||
app.attachStopCallback(function() {
|
||||
if (assistDemandedRestart) { return; }
|
||||
if (peer) {
|
||||
peer.destroy();
|
||||
log('Peer destroyed!')
|
||||
}
|
||||
});
|
||||
|
||||
app.attachStartCallback(function() {
|
||||
if (assistDemandedRestart) { return; }
|
||||
const peerID = `${app.getProjectKey()}-${app.getSessionID()}`
|
||||
const _opt = {
|
||||
// @ts-ignore
|
||||
host: app.getHost(),
|
||||
path: '/assist',
|
||||
port: location.protocol === 'http:' && appOptions.__DISABLE_SECURE_MODE ? 80 : 443,
|
||||
debug: appOptions.__debug_log ? 2 : 0, // 0 Print nothing //1 Prints only errors. / 2 Prints errors and warnings. / 3 Prints all logs.
|
||||
}
|
||||
if (options.config) {
|
||||
_opt['config'] = options.config
|
||||
}
|
||||
peer = new Peer(peerID, _opt);
|
||||
log('Peer created: ', peer)
|
||||
peer.on('error', e => warn("Peer error: ", e.type, e))
|
||||
peer.on('connection', function(conn) {
|
||||
window.addEventListener("beforeunload", () => conn.open && conn.send("unload"));
|
||||
log('Connecting...')
|
||||
|
||||
conn.on('open', function() {
|
||||
log('Connection opened.')
|
||||
assistDemandedRestart = true;
|
||||
app.stop();
|
||||
openDataConnections[conn.peer] = new BufferingConnection(conn)
|
||||
|
||||
const onAgentDisconnect = options.onAgentConnect();
|
||||
conn.on('close', () => {
|
||||
onAgentDisconnect && onAgentDisconnect();
|
||||
log("Connection close: ", conn.peer)
|
||||
delete openDataConnections[conn.peer] // TODO: check if works properly
|
||||
})
|
||||
app.start().then(() => { assistDemandedRestart = false })
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
let callingState: CallingState = CallingState.False;
|
||||
|
||||
peer.on('call', function(call) {
|
||||
log("Call: ", call)
|
||||
if (!peer) { return; }
|
||||
const dataConn: DataConnection | undefined =
|
||||
openDataConnections[call.peer]?.conn;
|
||||
if (callingState !== CallingState.False || !dataConn || !dataConn.open) {
|
||||
call.close();
|
||||
warn("Call closed instantly: ", callingState, dataConn, dataConn.open)
|
||||
return;
|
||||
}
|
||||
|
||||
function setCallingState(newState: CallingState) {
|
||||
if (newState === CallingState.True) {
|
||||
sessionStorage.setItem(options.session_calling_peer_key, call.peer);
|
||||
} else if (newState === CallingState.False) {
|
||||
sessionStorage.removeItem(options.session_calling_peer_key);
|
||||
}
|
||||
callingState = newState;
|
||||
}
|
||||
|
||||
const notifyCallEnd = () => {
|
||||
dataConn.open && dataConn.send("call_end");
|
||||
}
|
||||
|
||||
|
||||
let confirmAnswer: Promise<boolean>
|
||||
const callingPeer = sessionStorage.getItem(options.session_calling_peer_key)
|
||||
if (callingPeer === call.peer) {
|
||||
confirmAnswer = Promise.resolve(true)
|
||||
} else {
|
||||
setCallingState(CallingState.Requesting);
|
||||
const confirm = new ConfirmWindow(options.confirmText, options.confirmStyle);
|
||||
confirmAnswer = confirm.mount();
|
||||
dataConn.on('data', (data) => { // if call cancelled by a caller before confirmation
|
||||
if (data === "call_end") {
|
||||
log("Received call_end during confirm window opened")
|
||||
confirm.remove();
|
||||
setCallingState(CallingState.False);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
confirmAnswer.then(agreed => {
|
||||
if (!agreed || !dataConn.open) {
|
||||
!dataConn.open && warn("Call cancelled because data connection is closed.")
|
||||
call.close()
|
||||
notifyCallEnd()
|
||||
setCallingState(CallingState.False)
|
||||
return
|
||||
}
|
||||
|
||||
const onCallEnd = options.onCallStart()
|
||||
|
||||
const mouse = new Mouse()
|
||||
let callUI = new CallWindow()
|
||||
|
||||
const handleCallEnd = () => {
|
||||
onCallEnd && onCallEnd()
|
||||
mouse.remove();
|
||||
callUI.remove();
|
||||
setCallingState(CallingState.False);
|
||||
}
|
||||
const initiateCallEnd = () => {
|
||||
log("initiateCallEnd")
|
||||
call.close()
|
||||
notifyCallEnd();
|
||||
handleCallEnd();
|
||||
}
|
||||
RequestLocalStream().then(lStream => {
|
||||
dataConn.on("close", handleCallEnd); // For what case?
|
||||
//call.on('close', onClose); // Works from time to time (peerjs bug)
|
||||
const checkConnInterval = setInterval(() => {
|
||||
if (!dataConn.open) {
|
||||
initiateCallEnd();
|
||||
clearInterval(checkConnInterval);
|
||||
}
|
||||
if (!call.open) {
|
||||
handleCallEnd();
|
||||
clearInterval(checkConnInterval);
|
||||
}
|
||||
}, 3000);
|
||||
call.on('error', e => {
|
||||
warn("Call error:", e)
|
||||
initiateCallEnd()
|
||||
});
|
||||
|
||||
call.on('stream', function(rStream) {
|
||||
callUI.setRemoteStream(rStream);
|
||||
const onInteraction = () => { // only if hidden?
|
||||
callUI.playRemote()
|
||||
document.removeEventListener("click", onInteraction)
|
||||
}
|
||||
document.addEventListener("click", onInteraction)
|
||||
});
|
||||
dataConn.on('data', (data: any) => {
|
||||
log("Income data: ", data)
|
||||
if (!data) { return }
|
||||
if (data === "call_end") {
|
||||
return handleCallEnd();
|
||||
}
|
||||
if (data.name === 'string') {
|
||||
return callUI.setAssistentName(data.name);
|
||||
}
|
||||
if (data.type === "scroll" && Array.isArray(data.delta)) {
|
||||
return mouse.scroll(data.delta)
|
||||
}
|
||||
if (data.type === "click" && typeof data.x === 'number' && typeof data.y === 'number') {
|
||||
return mouse.click([ data.x, data.y ])
|
||||
}
|
||||
if (typeof data.x === 'number' && typeof data.y === 'number') {
|
||||
return mouse.move([ data.x, data.y ])
|
||||
}
|
||||
});
|
||||
|
||||
lStream.onVideoTrack(vTrack => {
|
||||
const sender = call.peerConnection.getSenders().find(s => s.track?.kind === "video")
|
||||
if (!sender) {
|
||||
warn("No video sender found")
|
||||
return
|
||||
}
|
||||
log("sender found:", sender)
|
||||
sender.replaceTrack(vTrack)
|
||||
})
|
||||
|
||||
callUI.setCallEndAction(initiateCallEnd)
|
||||
callUI.setLocalStream(lStream)
|
||||
call.answer(lStream.stream)
|
||||
setCallingState(CallingState.True)
|
||||
})
|
||||
.catch(e => {
|
||||
warn("Audio mediadevice request error:", e)
|
||||
handleCallEnd()
|
||||
});
|
||||
}).catch(); // in case of Confirm.remove() without any confirmation
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue