@openreplay/tracker-assist
Advanced tools
Comparing version 8.0.4-beta.0 to 9.0.0
@@ -0,1 +1,7 @@ | ||
## 9.0.0 | ||
- support for message compression inside plugin (requires v1.18 frontend) | ||
- support for assist-only mode (requires EE license) | ||
- open peer connection dynamically on call | ||
## 8.0.4 | ||
@@ -2,0 +8,0 @@ |
@@ -24,2 +24,8 @@ import type { Properties } from 'csstype'; | ||
callUITemplate?: string; | ||
compressionEnabled: boolean; | ||
/** | ||
* Minimum amount of messages in a batch to trigger compression run | ||
* @default 5000 | ||
* */ | ||
compressionMinBatchSize: number; | ||
} | ||
@@ -29,3 +35,3 @@ export default class Assist { | ||
private readonly noSecureMode; | ||
readonly version = "8.0.4-beta.0"; | ||
readonly version = "9.0.0"; | ||
private socket; | ||
@@ -32,0 +38,0 @@ private peer; |
@@ -15,2 +15,3 @@ "use strict"; | ||
const Canvas_js_1 = require("./Canvas.js"); | ||
const fflate_1 = require("fflate"); | ||
// TODO: fully specified strict check with no-any (everywhere) | ||
@@ -56,2 +57,4 @@ // @ts-ignore | ||
socketHost: '', | ||
compressionEnabled: false, | ||
compressionMinBatchSize: 5000, | ||
}, options); | ||
@@ -88,7 +91,35 @@ if (this.app.options.assistSocketHost) { | ||
if (this.agentsConnected) { | ||
const batchSize = messages.length; | ||
// @ts-ignore No need in statistics messages. TODO proper filter | ||
if (messages.length === 2 && messages[0]._id === 0 && messages[1]._id === 49) { | ||
if (batchSize === 2 && messages[0]._id === 0 && messages[1]._id === 49) { | ||
return; | ||
} | ||
this.emit('messages', messages); | ||
if (batchSize > this.options.compressionMinBatchSize && this.options.compressionEnabled) { | ||
const toSend = []; | ||
if (batchSize > 10000) { | ||
const middle = Math.floor(batchSize / 2); | ||
const firstHalf = messages.slice(0, middle); | ||
const secondHalf = messages.slice(middle); | ||
toSend.push(firstHalf); | ||
toSend.push(secondHalf); | ||
} | ||
else { | ||
toSend.push(messages); | ||
} | ||
toSend.forEach(batch => { | ||
const str = JSON.stringify(batch); | ||
const byteArr = new TextEncoder().encode(str); | ||
(0, fflate_1.gzip)(byteArr, { mtime: 0, }, (err, result) => { | ||
if (err) { | ||
this.emit('messages', batch); | ||
} | ||
else { | ||
this.emit('messages_gz', result); | ||
} | ||
}); | ||
}); | ||
} | ||
else { | ||
this.emit('messages', messages); | ||
} | ||
} | ||
@@ -141,3 +172,3 @@ }); | ||
'tabId': this.app.getTabId(), | ||
'sessionInfo': JSON.stringify(Object.assign({ 'uxtId': (_a = this.app.getUxtId()) !== null && _a !== void 0 ? _a : undefined, pageTitle: document.title, active: true }, this.app.getSessionInfo())), | ||
'sessionInfo': JSON.stringify(Object.assign({ 'uxtId': (_a = this.app.getUxtId()) !== null && _a !== void 0 ? _a : undefined, pageTitle: document.title, active: true, assistOnly: this.app.socketMode }, this.app.getSessionInfo())), | ||
}, | ||
@@ -304,2 +335,5 @@ transports: ['websocket',], | ||
callingAgents.set(id, name); | ||
if (!this.peer) { | ||
setupPeer(); | ||
} | ||
updateCallerNames(); | ||
@@ -337,3 +371,5 @@ }); | ||
const lStreams = {}; | ||
// const callingPeers: Map<string, { call: MediaConnection, lStream: LocalStream }> = new Map() // Maybe | ||
function updateCallerNames() { | ||
callUI === null || callUI === void 0 ? void 0 : callUI.setAssistentName(callingAgents); | ||
} | ||
function endAgentCall(id) { | ||
@@ -349,50 +385,2 @@ callingAgents.delete(id); | ||
} | ||
// PeerJS call (todo: use native WebRTC) | ||
const peerOptions = { | ||
host: this.getHost(), | ||
path: this.getBasePrefixUrl() + '/assist', | ||
port: location.protocol === 'http:' && this.noSecureMode ? 80 : 443, | ||
debug: 2, //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 = new safeCastedPeer(peerID, peerOptions); | ||
this.peer = peer; | ||
let peerReconnectAttempts = 0; | ||
// @ts-ignore (peerjs typing) | ||
peer.on('error', e => app.debug.warn('Peer error: ', e.type, e)); | ||
peer.on('disconnected', () => { | ||
if (peerReconnectAttempts < 30) { | ||
this.peerReconnectTimeout = setTimeout(() => { | ||
if (this.app.active() && !peer.destroyed) { | ||
peer.reconnect(); | ||
} | ||
}, Math.min(peerReconnectAttempts, 8) * 2 * 1000); | ||
peerReconnectAttempts += 1; | ||
} | ||
}); | ||
function updateCallerNames() { | ||
callUI === null || callUI === void 0 ? void 0 : callUI.setAssistentName(callingAgents); | ||
} | ||
const closeCallConfirmWindow = () => { | ||
if (callConfirmWindow) { | ||
callConfirmWindow.remove(); | ||
callConfirmWindow = null; | ||
callConfirmAnswer = null; | ||
} | ||
}; | ||
const requestCallConfirm = () => { | ||
if (callConfirmAnswer) { // Already asking | ||
return callConfirmAnswer; | ||
} | ||
callConfirmWindow = new ConfirmWindow_js_1.default((0, defaults_js_1.callConfirmDefault)(this.options.callConfirm || { | ||
text: this.options.confirmText, | ||
style: this.options.confirmStyle, | ||
})); // TODO: reuse ? | ||
return callConfirmAnswer = callConfirmWindow.mount().then(answer => { | ||
closeCallConfirmWindow(); | ||
return answer; | ||
}); | ||
}; | ||
const handleCallEnd = () => { | ||
@@ -423,95 +411,142 @@ var _a; | ||
}; | ||
const initiateCallEnd = () => { | ||
this.emit('call_end'); | ||
handleCallEnd(); | ||
const closeCallConfirmWindow = () => { | ||
if (callConfirmWindow) { | ||
callConfirmWindow.remove(); | ||
callConfirmWindow = null; | ||
callConfirmAnswer = null; | ||
} | ||
}; | ||
const updateVideoFeed = ({ enabled, }) => { var _a; return this.emit('videofeed', { streamId: (_a = this.peer) === null || _a === void 0 ? void 0 : _a.id, enabled, }); }; | ||
peer.on('call', (call) => { | ||
app.debug.log('Incoming call from', call.peer); | ||
let confirmAnswer; | ||
const callingPeerIds = JSON.parse(sessionStorage.getItem(this.options.session_calling_peer_key) || '[]'); | ||
if (callingPeerIds.includes(call.peer) || this.callingState === CallingState.True) { | ||
confirmAnswer = Promise.resolve(true); | ||
// PeerJS call (todo: use native WebRTC) | ||
const peerOptions = { | ||
host: this.getHost(), | ||
path: this.getBasePrefixUrl() + '/assist', | ||
port: location.protocol === 'http:' && this.noSecureMode ? 80 : 443, | ||
debug: 2, //appOptions.__debug_log ? 2 : 0, // 0 Print nothing //1 Prints only errors. / 2 Prints errors and warnings. / 3 Prints all logs. | ||
}; | ||
const setupPeer = () => { | ||
if (this.options.config) { | ||
peerOptions['config'] = this.options.config; | ||
} | ||
else { | ||
this.setCallingState(CallingState.Requesting); | ||
confirmAnswer = requestCallConfirm(); | ||
this.playNotificationSound(); // For every new agent during confirmation here | ||
// TODO: only one (latest) timeout | ||
setTimeout(() => { | ||
if (this.callingState !== CallingState.Requesting) { | ||
return; | ||
} | ||
initiateCallEnd(); | ||
}, 30000); | ||
} | ||
confirmAnswer.then(async (agreed) => { | ||
var _a, _b, _c, _d; | ||
if (!agreed) { | ||
initiateCallEnd(); | ||
(_b = (_a = this.options).onCallDeny) === null || _b === void 0 ? void 0 : _b.call(_a); | ||
return; | ||
const peer = new safeCastedPeer(peerID, peerOptions); | ||
this.peer = peer; | ||
let peerReconnectAttempts = 0; | ||
// @ts-ignore (peerjs typing) | ||
peer.on('error', e => app.debug.warn('Peer error: ', e.type, e)); | ||
peer.on('disconnected', () => { | ||
if (peerReconnectAttempts < 30) { | ||
this.peerReconnectTimeout = setTimeout(() => { | ||
if (this.app.active() && !peer.destroyed) { | ||
peer.reconnect(); | ||
} | ||
}, Math.min(peerReconnectAttempts, 8) * 2 * 1000); | ||
peerReconnectAttempts += 1; | ||
} | ||
// Request local stream for the new connection | ||
try { | ||
// lStreams are reusable so fare we don't delete them in the `endAgentCall` | ||
if (!lStreams[call.peer]) { | ||
app.debug.log('starting new stream for', call.peer); | ||
lStreams[call.peer] = await (0, LocalStream_js_1.default)(); | ||
} | ||
calls[call.peer] = call; | ||
}); | ||
const requestCallConfirm = () => { | ||
if (callConfirmAnswer) { // Already asking | ||
return callConfirmAnswer; | ||
} | ||
catch (e) { | ||
app.debug.error('Audio media device request error:', e); | ||
initiateCallEnd(); | ||
return; | ||
callConfirmWindow = new ConfirmWindow_js_1.default((0, defaults_js_1.callConfirmDefault)(this.options.callConfirm || { | ||
text: this.options.confirmText, | ||
style: this.options.confirmStyle, | ||
})); // TODO: reuse ? | ||
return callConfirmAnswer = callConfirmWindow.mount().then(answer => { | ||
closeCallConfirmWindow(); | ||
return answer; | ||
}); | ||
}; | ||
const initiateCallEnd = () => { | ||
this.emit('call_end'); | ||
handleCallEnd(); | ||
}; | ||
const updateVideoFeed = ({ enabled, }) => { var _a; return this.emit('videofeed', { streamId: (_a = this.peer) === null || _a === void 0 ? void 0 : _a.id, enabled, }); }; | ||
peer.on('call', (call) => { | ||
app.debug.log('Incoming call from', call.peer); | ||
let confirmAnswer; | ||
const callingPeerIds = JSON.parse(sessionStorage.getItem(this.options.session_calling_peer_key) || '[]'); | ||
if (callingPeerIds.includes(call.peer) || this.callingState === CallingState.True) { | ||
confirmAnswer = Promise.resolve(true); | ||
} | ||
if (!callUI) { | ||
callUI = new CallWindow_js_1.default(app.debug.error, this.options.callUITemplate); | ||
callUI.setVideoToggleCallback(updateVideoFeed); | ||
else { | ||
this.setCallingState(CallingState.Requesting); | ||
confirmAnswer = requestCallConfirm(); | ||
this.playNotificationSound(); // For every new agent during confirmation here | ||
// TODO: only one (latest) timeout | ||
setTimeout(() => { | ||
if (this.callingState !== CallingState.Requesting) { | ||
return; | ||
} | ||
initiateCallEnd(); | ||
}, 30000); | ||
} | ||
callUI.showControls(initiateCallEnd); | ||
if (!annot) { | ||
annot = new AnnotationCanvas_js_1.default(); | ||
annot.mount(); | ||
} | ||
// have to be updated | ||
callUI.setLocalStreams(Object.values(lStreams)); | ||
call.on('error', e => { | ||
app.debug.warn('Call error:', e); | ||
initiateCallEnd(); | ||
}); | ||
call.on('stream', (rStream) => { | ||
callUI === null || callUI === void 0 ? void 0 : callUI.addRemoteStream(rStream, call.peer); | ||
const onInteraction = () => { | ||
callUI === null || callUI === void 0 ? void 0 : callUI.playRemote(); | ||
document.removeEventListener('click', onInteraction); | ||
}; | ||
document.addEventListener('click', onInteraction); | ||
}); | ||
// remote video on/off/camera change | ||
lStreams[call.peer].onVideoTrack(vTrack => { | ||
const sender = call.peerConnection.getSenders().find(s => { var _a; return ((_a = s.track) === null || _a === void 0 ? void 0 : _a.kind) === 'video'; }); | ||
if (!sender) { | ||
app.debug.warn('No video sender found'); | ||
confirmAnswer.then(async (agreed) => { | ||
var _a, _b, _c, _d; | ||
if (!agreed) { | ||
initiateCallEnd(); | ||
(_b = (_a = this.options).onCallDeny) === null || _b === void 0 ? void 0 : _b.call(_a); | ||
return; | ||
} | ||
app.debug.log('sender found:', sender); | ||
void sender.replaceTrack(vTrack); | ||
// Request local stream for the new connection | ||
try { | ||
// lStreams are reusable so fare we don't delete them in the `endAgentCall` | ||
if (!lStreams[call.peer]) { | ||
app.debug.log('starting new stream for', call.peer); | ||
lStreams[call.peer] = await (0, LocalStream_js_1.default)(); | ||
} | ||
calls[call.peer] = call; | ||
} | ||
catch (e) { | ||
app.debug.error('Audio media device request error:', e); | ||
initiateCallEnd(); | ||
return; | ||
} | ||
if (!callUI) { | ||
callUI = new CallWindow_js_1.default(app.debug.error, this.options.callUITemplate); | ||
callUI.setVideoToggleCallback(updateVideoFeed); | ||
} | ||
callUI.showControls(initiateCallEnd); | ||
if (!annot) { | ||
annot = new AnnotationCanvas_js_1.default(); | ||
annot.mount(); | ||
} | ||
// have to be updated | ||
callUI.setLocalStreams(Object.values(lStreams)); | ||
call.on('error', e => { | ||
app.debug.warn('Call error:', e); | ||
initiateCallEnd(); | ||
}); | ||
call.on('stream', (rStream) => { | ||
callUI === null || callUI === void 0 ? void 0 : callUI.addRemoteStream(rStream, call.peer); | ||
const onInteraction = () => { | ||
callUI === null || callUI === void 0 ? void 0 : callUI.playRemote(); | ||
document.removeEventListener('click', onInteraction); | ||
}; | ||
document.addEventListener('click', onInteraction); | ||
}); | ||
// remote video on/off/camera change | ||
lStreams[call.peer].onVideoTrack(vTrack => { | ||
const sender = call.peerConnection.getSenders().find(s => { var _a; return ((_a = s.track) === null || _a === void 0 ? void 0 : _a.kind) === 'video'; }); | ||
if (!sender) { | ||
app.debug.warn('No video sender found'); | ||
return; | ||
} | ||
app.debug.log('sender found:', sender); | ||
void sender.replaceTrack(vTrack); | ||
}); | ||
call.answer(lStreams[call.peer].stream); | ||
document.addEventListener('visibilitychange', () => { | ||
initiateCallEnd(); | ||
}); | ||
this.setCallingState(CallingState.True); | ||
if (!callEndCallback) { | ||
callEndCallback = (_d = (_c = this.options).onCallStart) === null || _d === void 0 ? void 0 : _d.call(_c); | ||
} | ||
const callingPeerIds = Object.keys(calls); | ||
sessionStorage.setItem(this.options.session_calling_peer_key, JSON.stringify(callingPeerIds)); | ||
this.emit('UPDATE_SESSION', { agentIds: callingPeerIds, isCallActive: true, }); | ||
}).catch(reason => { | ||
app.debug.log(reason); | ||
}); | ||
call.answer(lStreams[call.peer].stream); | ||
document.addEventListener('visibilitychange', () => { | ||
initiateCallEnd(); | ||
}); | ||
this.setCallingState(CallingState.True); | ||
if (!callEndCallback) { | ||
callEndCallback = (_d = (_c = this.options).onCallStart) === null || _d === void 0 ? void 0 : _d.call(_c); | ||
} | ||
const callingPeerIds = Object.keys(calls); | ||
sessionStorage.setItem(this.options.session_calling_peer_key, JSON.stringify(callingPeerIds)); | ||
this.emit('UPDATE_SESSION', { agentIds: callingPeerIds, isCallActive: true, }); | ||
}).catch(reason => { | ||
app.debug.log(reason); | ||
}); | ||
}); | ||
}; | ||
const startCanvasStream = (stream, id) => { | ||
@@ -565,3 +600,3 @@ var _a; | ||
var _a; | ||
// sometimes means new agent connected so we keep id for control | ||
// sometimes means new agent connected, so we keep id for control | ||
(_a = this.remoteControl) === null || _a === void 0 ? void 0 : _a.releaseControl(false, true); | ||
@@ -568,0 +603,0 @@ if (this.peerReconnectTimeout) { |
@@ -1,1 +0,1 @@ | ||
export declare const pkgVersion = "8.0.4-beta.0"; | ||
export declare const pkgVersion = "9.0.0"; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.pkgVersion = void 0; | ||
exports.pkgVersion = "8.0.4-beta.0"; | ||
exports.pkgVersion = "9.0.0"; |
@@ -24,2 +24,8 @@ import type { Properties } from 'csstype'; | ||
callUITemplate?: string; | ||
compressionEnabled: boolean; | ||
/** | ||
* Minimum amount of messages in a batch to trigger compression run | ||
* @default 5000 | ||
* */ | ||
compressionMinBatchSize: number; | ||
} | ||
@@ -29,3 +35,3 @@ export default class Assist { | ||
private readonly noSecureMode; | ||
readonly version = "8.0.4-beta.0"; | ||
readonly version = "9.0.0"; | ||
private socket; | ||
@@ -32,0 +38,0 @@ private peer; |
@@ -13,2 +13,3 @@ import { connect, } from 'socket.io-client'; | ||
import Canvas from './Canvas.js'; | ||
import { gzip, } from 'fflate'; | ||
// TODO: fully specified strict check with no-any (everywhere) | ||
@@ -54,2 +55,4 @@ // @ts-ignore | ||
socketHost: '', | ||
compressionEnabled: false, | ||
compressionMinBatchSize: 5000, | ||
}, options); | ||
@@ -86,7 +89,35 @@ if (this.app.options.assistSocketHost) { | ||
if (this.agentsConnected) { | ||
const batchSize = messages.length; | ||
// @ts-ignore No need in statistics messages. TODO proper filter | ||
if (messages.length === 2 && messages[0]._id === 0 && messages[1]._id === 49) { | ||
if (batchSize === 2 && messages[0]._id === 0 && messages[1]._id === 49) { | ||
return; | ||
} | ||
this.emit('messages', messages); | ||
if (batchSize > this.options.compressionMinBatchSize && this.options.compressionEnabled) { | ||
const toSend = []; | ||
if (batchSize > 10000) { | ||
const middle = Math.floor(batchSize / 2); | ||
const firstHalf = messages.slice(0, middle); | ||
const secondHalf = messages.slice(middle); | ||
toSend.push(firstHalf); | ||
toSend.push(secondHalf); | ||
} | ||
else { | ||
toSend.push(messages); | ||
} | ||
toSend.forEach(batch => { | ||
const str = JSON.stringify(batch); | ||
const byteArr = new TextEncoder().encode(str); | ||
gzip(byteArr, { mtime: 0, }, (err, result) => { | ||
if (err) { | ||
this.emit('messages', batch); | ||
} | ||
else { | ||
this.emit('messages_gz', result); | ||
} | ||
}); | ||
}); | ||
} | ||
else { | ||
this.emit('messages', messages); | ||
} | ||
} | ||
@@ -139,3 +170,3 @@ }); | ||
'tabId': this.app.getTabId(), | ||
'sessionInfo': JSON.stringify(Object.assign({ 'uxtId': (_a = this.app.getUxtId()) !== null && _a !== void 0 ? _a : undefined, pageTitle: document.title, active: true }, this.app.getSessionInfo())), | ||
'sessionInfo': JSON.stringify(Object.assign({ 'uxtId': (_a = this.app.getUxtId()) !== null && _a !== void 0 ? _a : undefined, pageTitle: document.title, active: true, assistOnly: this.app.socketMode }, this.app.getSessionInfo())), | ||
}, | ||
@@ -302,2 +333,5 @@ transports: ['websocket',], | ||
callingAgents.set(id, name); | ||
if (!this.peer) { | ||
setupPeer(); | ||
} | ||
updateCallerNames(); | ||
@@ -335,3 +369,5 @@ }); | ||
const lStreams = {}; | ||
// const callingPeers: Map<string, { call: MediaConnection, lStream: LocalStream }> = new Map() // Maybe | ||
function updateCallerNames() { | ||
callUI === null || callUI === void 0 ? void 0 : callUI.setAssistentName(callingAgents); | ||
} | ||
function endAgentCall(id) { | ||
@@ -347,50 +383,2 @@ callingAgents.delete(id); | ||
} | ||
// PeerJS call (todo: use native WebRTC) | ||
const peerOptions = { | ||
host: this.getHost(), | ||
path: this.getBasePrefixUrl() + '/assist', | ||
port: location.protocol === 'http:' && this.noSecureMode ? 80 : 443, | ||
debug: 2, //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 = new safeCastedPeer(peerID, peerOptions); | ||
this.peer = peer; | ||
let peerReconnectAttempts = 0; | ||
// @ts-ignore (peerjs typing) | ||
peer.on('error', e => app.debug.warn('Peer error: ', e.type, e)); | ||
peer.on('disconnected', () => { | ||
if (peerReconnectAttempts < 30) { | ||
this.peerReconnectTimeout = setTimeout(() => { | ||
if (this.app.active() && !peer.destroyed) { | ||
peer.reconnect(); | ||
} | ||
}, Math.min(peerReconnectAttempts, 8) * 2 * 1000); | ||
peerReconnectAttempts += 1; | ||
} | ||
}); | ||
function updateCallerNames() { | ||
callUI === null || callUI === void 0 ? void 0 : callUI.setAssistentName(callingAgents); | ||
} | ||
const closeCallConfirmWindow = () => { | ||
if (callConfirmWindow) { | ||
callConfirmWindow.remove(); | ||
callConfirmWindow = null; | ||
callConfirmAnswer = null; | ||
} | ||
}; | ||
const requestCallConfirm = () => { | ||
if (callConfirmAnswer) { // Already asking | ||
return callConfirmAnswer; | ||
} | ||
callConfirmWindow = new ConfirmWindow(callConfirmDefault(this.options.callConfirm || { | ||
text: this.options.confirmText, | ||
style: this.options.confirmStyle, | ||
})); // TODO: reuse ? | ||
return callConfirmAnswer = callConfirmWindow.mount().then(answer => { | ||
closeCallConfirmWindow(); | ||
return answer; | ||
}); | ||
}; | ||
const handleCallEnd = () => { | ||
@@ -421,95 +409,142 @@ var _a; | ||
}; | ||
const initiateCallEnd = () => { | ||
this.emit('call_end'); | ||
handleCallEnd(); | ||
const closeCallConfirmWindow = () => { | ||
if (callConfirmWindow) { | ||
callConfirmWindow.remove(); | ||
callConfirmWindow = null; | ||
callConfirmAnswer = null; | ||
} | ||
}; | ||
const updateVideoFeed = ({ enabled, }) => { var _a; return this.emit('videofeed', { streamId: (_a = this.peer) === null || _a === void 0 ? void 0 : _a.id, enabled, }); }; | ||
peer.on('call', (call) => { | ||
app.debug.log('Incoming call from', call.peer); | ||
let confirmAnswer; | ||
const callingPeerIds = JSON.parse(sessionStorage.getItem(this.options.session_calling_peer_key) || '[]'); | ||
if (callingPeerIds.includes(call.peer) || this.callingState === CallingState.True) { | ||
confirmAnswer = Promise.resolve(true); | ||
// PeerJS call (todo: use native WebRTC) | ||
const peerOptions = { | ||
host: this.getHost(), | ||
path: this.getBasePrefixUrl() + '/assist', | ||
port: location.protocol === 'http:' && this.noSecureMode ? 80 : 443, | ||
debug: 2, //appOptions.__debug_log ? 2 : 0, // 0 Print nothing //1 Prints only errors. / 2 Prints errors and warnings. / 3 Prints all logs. | ||
}; | ||
const setupPeer = () => { | ||
if (this.options.config) { | ||
peerOptions['config'] = this.options.config; | ||
} | ||
else { | ||
this.setCallingState(CallingState.Requesting); | ||
confirmAnswer = requestCallConfirm(); | ||
this.playNotificationSound(); // For every new agent during confirmation here | ||
// TODO: only one (latest) timeout | ||
setTimeout(() => { | ||
if (this.callingState !== CallingState.Requesting) { | ||
return; | ||
} | ||
initiateCallEnd(); | ||
}, 30000); | ||
} | ||
confirmAnswer.then(async (agreed) => { | ||
var _a, _b, _c, _d; | ||
if (!agreed) { | ||
initiateCallEnd(); | ||
(_b = (_a = this.options).onCallDeny) === null || _b === void 0 ? void 0 : _b.call(_a); | ||
return; | ||
const peer = new safeCastedPeer(peerID, peerOptions); | ||
this.peer = peer; | ||
let peerReconnectAttempts = 0; | ||
// @ts-ignore (peerjs typing) | ||
peer.on('error', e => app.debug.warn('Peer error: ', e.type, e)); | ||
peer.on('disconnected', () => { | ||
if (peerReconnectAttempts < 30) { | ||
this.peerReconnectTimeout = setTimeout(() => { | ||
if (this.app.active() && !peer.destroyed) { | ||
peer.reconnect(); | ||
} | ||
}, Math.min(peerReconnectAttempts, 8) * 2 * 1000); | ||
peerReconnectAttempts += 1; | ||
} | ||
// Request local stream for the new connection | ||
try { | ||
// lStreams are reusable so fare we don't delete them in the `endAgentCall` | ||
if (!lStreams[call.peer]) { | ||
app.debug.log('starting new stream for', call.peer); | ||
lStreams[call.peer] = await RequestLocalStream(); | ||
} | ||
calls[call.peer] = call; | ||
}); | ||
const requestCallConfirm = () => { | ||
if (callConfirmAnswer) { // Already asking | ||
return callConfirmAnswer; | ||
} | ||
catch (e) { | ||
app.debug.error('Audio media device request error:', e); | ||
initiateCallEnd(); | ||
return; | ||
callConfirmWindow = new ConfirmWindow(callConfirmDefault(this.options.callConfirm || { | ||
text: this.options.confirmText, | ||
style: this.options.confirmStyle, | ||
})); // TODO: reuse ? | ||
return callConfirmAnswer = callConfirmWindow.mount().then(answer => { | ||
closeCallConfirmWindow(); | ||
return answer; | ||
}); | ||
}; | ||
const initiateCallEnd = () => { | ||
this.emit('call_end'); | ||
handleCallEnd(); | ||
}; | ||
const updateVideoFeed = ({ enabled, }) => { var _a; return this.emit('videofeed', { streamId: (_a = this.peer) === null || _a === void 0 ? void 0 : _a.id, enabled, }); }; | ||
peer.on('call', (call) => { | ||
app.debug.log('Incoming call from', call.peer); | ||
let confirmAnswer; | ||
const callingPeerIds = JSON.parse(sessionStorage.getItem(this.options.session_calling_peer_key) || '[]'); | ||
if (callingPeerIds.includes(call.peer) || this.callingState === CallingState.True) { | ||
confirmAnswer = Promise.resolve(true); | ||
} | ||
if (!callUI) { | ||
callUI = new CallWindow(app.debug.error, this.options.callUITemplate); | ||
callUI.setVideoToggleCallback(updateVideoFeed); | ||
else { | ||
this.setCallingState(CallingState.Requesting); | ||
confirmAnswer = requestCallConfirm(); | ||
this.playNotificationSound(); // For every new agent during confirmation here | ||
// TODO: only one (latest) timeout | ||
setTimeout(() => { | ||
if (this.callingState !== CallingState.Requesting) { | ||
return; | ||
} | ||
initiateCallEnd(); | ||
}, 30000); | ||
} | ||
callUI.showControls(initiateCallEnd); | ||
if (!annot) { | ||
annot = new AnnotationCanvas(); | ||
annot.mount(); | ||
} | ||
// have to be updated | ||
callUI.setLocalStreams(Object.values(lStreams)); | ||
call.on('error', e => { | ||
app.debug.warn('Call error:', e); | ||
initiateCallEnd(); | ||
}); | ||
call.on('stream', (rStream) => { | ||
callUI === null || callUI === void 0 ? void 0 : callUI.addRemoteStream(rStream, call.peer); | ||
const onInteraction = () => { | ||
callUI === null || callUI === void 0 ? void 0 : callUI.playRemote(); | ||
document.removeEventListener('click', onInteraction); | ||
}; | ||
document.addEventListener('click', onInteraction); | ||
}); | ||
// remote video on/off/camera change | ||
lStreams[call.peer].onVideoTrack(vTrack => { | ||
const sender = call.peerConnection.getSenders().find(s => { var _a; return ((_a = s.track) === null || _a === void 0 ? void 0 : _a.kind) === 'video'; }); | ||
if (!sender) { | ||
app.debug.warn('No video sender found'); | ||
confirmAnswer.then(async (agreed) => { | ||
var _a, _b, _c, _d; | ||
if (!agreed) { | ||
initiateCallEnd(); | ||
(_b = (_a = this.options).onCallDeny) === null || _b === void 0 ? void 0 : _b.call(_a); | ||
return; | ||
} | ||
app.debug.log('sender found:', sender); | ||
void sender.replaceTrack(vTrack); | ||
// Request local stream for the new connection | ||
try { | ||
// lStreams are reusable so fare we don't delete them in the `endAgentCall` | ||
if (!lStreams[call.peer]) { | ||
app.debug.log('starting new stream for', call.peer); | ||
lStreams[call.peer] = await RequestLocalStream(); | ||
} | ||
calls[call.peer] = call; | ||
} | ||
catch (e) { | ||
app.debug.error('Audio media device request error:', e); | ||
initiateCallEnd(); | ||
return; | ||
} | ||
if (!callUI) { | ||
callUI = new CallWindow(app.debug.error, this.options.callUITemplate); | ||
callUI.setVideoToggleCallback(updateVideoFeed); | ||
} | ||
callUI.showControls(initiateCallEnd); | ||
if (!annot) { | ||
annot = new AnnotationCanvas(); | ||
annot.mount(); | ||
} | ||
// have to be updated | ||
callUI.setLocalStreams(Object.values(lStreams)); | ||
call.on('error', e => { | ||
app.debug.warn('Call error:', e); | ||
initiateCallEnd(); | ||
}); | ||
call.on('stream', (rStream) => { | ||
callUI === null || callUI === void 0 ? void 0 : callUI.addRemoteStream(rStream, call.peer); | ||
const onInteraction = () => { | ||
callUI === null || callUI === void 0 ? void 0 : callUI.playRemote(); | ||
document.removeEventListener('click', onInteraction); | ||
}; | ||
document.addEventListener('click', onInteraction); | ||
}); | ||
// remote video on/off/camera change | ||
lStreams[call.peer].onVideoTrack(vTrack => { | ||
const sender = call.peerConnection.getSenders().find(s => { var _a; return ((_a = s.track) === null || _a === void 0 ? void 0 : _a.kind) === 'video'; }); | ||
if (!sender) { | ||
app.debug.warn('No video sender found'); | ||
return; | ||
} | ||
app.debug.log('sender found:', sender); | ||
void sender.replaceTrack(vTrack); | ||
}); | ||
call.answer(lStreams[call.peer].stream); | ||
document.addEventListener('visibilitychange', () => { | ||
initiateCallEnd(); | ||
}); | ||
this.setCallingState(CallingState.True); | ||
if (!callEndCallback) { | ||
callEndCallback = (_d = (_c = this.options).onCallStart) === null || _d === void 0 ? void 0 : _d.call(_c); | ||
} | ||
const callingPeerIds = Object.keys(calls); | ||
sessionStorage.setItem(this.options.session_calling_peer_key, JSON.stringify(callingPeerIds)); | ||
this.emit('UPDATE_SESSION', { agentIds: callingPeerIds, isCallActive: true, }); | ||
}).catch(reason => { | ||
app.debug.log(reason); | ||
}); | ||
call.answer(lStreams[call.peer].stream); | ||
document.addEventListener('visibilitychange', () => { | ||
initiateCallEnd(); | ||
}); | ||
this.setCallingState(CallingState.True); | ||
if (!callEndCallback) { | ||
callEndCallback = (_d = (_c = this.options).onCallStart) === null || _d === void 0 ? void 0 : _d.call(_c); | ||
} | ||
const callingPeerIds = Object.keys(calls); | ||
sessionStorage.setItem(this.options.session_calling_peer_key, JSON.stringify(callingPeerIds)); | ||
this.emit('UPDATE_SESSION', { agentIds: callingPeerIds, isCallActive: true, }); | ||
}).catch(reason => { | ||
app.debug.log(reason); | ||
}); | ||
}); | ||
}; | ||
const startCanvasStream = (stream, id) => { | ||
@@ -563,3 +598,3 @@ var _a; | ||
var _a; | ||
// sometimes means new agent connected so we keep id for control | ||
// sometimes means new agent connected, so we keep id for control | ||
(_a = this.remoteControl) === null || _a === void 0 ? void 0 : _a.releaseControl(false, true); | ||
@@ -566,0 +601,0 @@ if (this.peerReconnectTimeout) { |
@@ -1,1 +0,1 @@ | ||
export declare const pkgVersion = "8.0.4-beta.0"; | ||
export declare const pkgVersion = "9.0.0"; |
@@ -1,1 +0,1 @@ | ||
export const pkgVersion = "8.0.4-beta.0"; | ||
export const pkgVersion = "9.0.0"; |
{ | ||
"name": "@openreplay/tracker-assist", | ||
"description": "Tracker plugin for screen assistance through the WebRTC", | ||
"version": "8.0.4-beta.0", | ||
"version": "9.0.0", | ||
"keywords": [ | ||
@@ -33,10 +33,11 @@ "WebRTC", | ||
"csstype": "^3.0.10", | ||
"peerjs": "1.3.2", | ||
"fflate": "^0.8.2", | ||
"peerjs": "1.5.1", | ||
"socket.io-client": "^4.7.2" | ||
}, | ||
"peerDependencies": { | ||
"@openreplay/tracker": "^12.0.1" | ||
"@openreplay/tracker": "^13.0.0" | ||
}, | ||
"devDependencies": { | ||
"@openreplay/tracker": "12.0.7", | ||
"@openreplay/tracker": "file:../tracker", | ||
"@typescript-eslint/eslint-plugin": "^5.30.0", | ||
@@ -43,0 +44,0 @@ "@typescript-eslint/parser": "^5.30.0", |
Sorry, the diff of this file is not supported yet
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
428017
4384
1
5
+ Addedfflate@^0.8.2
+ Added@cbor-extract/cbor-extract-darwin-arm64@2.2.0(transitive)
+ Added@cbor-extract/cbor-extract-darwin-x64@2.2.0(transitive)
+ Added@cbor-extract/cbor-extract-linux-arm@2.2.0(transitive)
+ Added@cbor-extract/cbor-extract-linux-arm64@2.2.0(transitive)
+ Added@cbor-extract/cbor-extract-linux-x64@2.2.0(transitive)
+ Added@cbor-extract/cbor-extract-win32-x64@2.2.0(transitive)
+ Added@msgpack/msgpack@2.8.0(transitive)
+ Added@openreplay/tracker@13.0.2(transitive)
+ Addedcbor-extract@2.2.0(transitive)
+ Addedcbor-x@1.6.0(transitive)
+ Addeddetect-libc@2.0.3(transitive)
+ Addedeventemitter3@4.0.7(transitive)
+ Addednode-gyp-build-optional-packages@5.1.1(transitive)
+ Addedpeerjs@1.5.1(transitive)
+ Addedpeerjs-js-binarypack@2.1.0(transitive)
+ Addedsdp@3.2.0(transitive)
+ Addedwebrtc-adapter@8.2.3(transitive)
- Removed@openreplay/tracker@12.0.12(transitive)
- Removed@types/node@10.17.60(transitive)
- Removedeventemitter3@3.1.2(transitive)
- Removedpeerjs@1.3.2(transitive)
- Removedpeerjs-js-binarypack@1.0.1(transitive)
- Removedrtcpeerconnection-shim@1.2.15(transitive)
- Removedsdp@2.12.0(transitive)
- Removedwebrtc-adapter@7.7.1(transitive)
Updatedpeerjs@1.5.1