feat (tracker-assist): 3.4.9: focus on remote click & remote scroll & less messages per send for some browsers

This commit is contained in:
ShiKhu 2021-12-01 21:14:11 +01:00
parent 1809c2eda1
commit f50355a67c
6 changed files with 53 additions and 14 deletions

View file

@ -1,6 +1,6 @@
{ {
"name": "@openreplay/tracker-assist", "name": "@openreplay/tracker-assist",
"version": "3.4.7", "version": "3.4.8",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View file

@ -1,7 +1,7 @@
{ {
"name": "@openreplay/tracker-assist", "name": "@openreplay/tracker-assist",
"description": "Tracker plugin for screen assistance through the WebRTC", "description": "Tracker plugin for screen assistance through the WebRTC",
"version": "3.4.8", "version": "3.4.9",
"keywords": [ "keywords": [
"WebRTC", "WebRTC",
"assistance", "assistance",

View file

@ -5,18 +5,27 @@ interface Message {
encode(w: any): boolean; encode(w: any): boolean;
} }
// 16kb should be max according to specification
const crOrFf: boolean =
typeof navigator !== "undefined" &&
(navigator.userAgent.indexOf("Chrom") !== -1 || // Chrome && Chromium
navigator.userAgent.indexOf("Firefox") !== -1);
const MESSAGES_PER_SEND = crOrFf ? 500 : 100
// Bffering required in case of webRTC // Bffering required in case of webRTC
export default class BufferingConnection { export default class BufferingConnection {
private readonly buffer: Message[][] = [] private readonly buffer: Message[][] = []
private buffering: boolean = false private buffering: boolean = false
constructor(readonly conn: DataConnection){} constructor(readonly conn: DataConnection,
private readonly msgsPerSend: number = MESSAGES_PER_SEND){}
private sendNext() { private sendNext() {
if (this.buffer.length) { if (this.buffer.length) {
setTimeout(() => { setTimeout(() => {
this.conn.send(this.buffer.shift()) this.conn.send(this.buffer.shift())
this.sendNext() this.sendNext()
}, 50) }, 15)
} else { } else {
this.buffering = false this.buffering = false
} }
@ -26,7 +35,7 @@ export default class BufferingConnection {
if (!this.conn.open) { return; } if (!this.conn.open) { return; }
let i = 0; let i = 0;
while (i < messages.length) { while (i < messages.length) {
this.buffer.push(messages.slice(i, i+=1000)) this.buffer.push(messages.slice(i, i+=this.msgsPerSend))
} }
if (!this.buffering) { if (!this.buffering) {
this.buffering = true this.buffering = true

View file

@ -1,8 +1,7 @@
export default class Mouse { export default class Mouse {
private mouse: HTMLDivElement private mouse: HTMLDivElement
private position: [number,number] = [0,0]
constructor() { constructor() {
this.mouse = document.createElement('div'); this.mouse = document.createElement('div');
Object.assign(this.mouse.style, { Object.assign(this.mouse.style, {
@ -17,13 +16,18 @@ export default class Mouse {
document.body.appendChild(this.mouse); document.body.appendChild(this.mouse);
} }
move({x, y}: {x?: number, y?: number}) { move({x, y}: {x: number, y: number}) {
this.position = [x, y];
Object.assign(this.mouse.style, { Object.assign(this.mouse.style, {
left: `${x || 0}px`, left: `${x || 0}px`,
top: `${y || 0}px` top: `${y || 0}px`
}) })
} }
getPosition(): [ number, number] {
return this.position;
}
remove() { remove() {
if (this.mouse.parentElement) { if (this.mouse.parentElement) {
document.body.removeChild(this.mouse); document.body.removeChild(this.mouse);

View file

@ -5,4 +5,4 @@
*/ */
// @ts-ignore // @ts-ignore
window.parcelRequire = window.parcelRequire || undefined; typeof window !== "undefined" && (window.parcelRequire = window.parcelRequire || undefined);

View file

@ -15,6 +15,7 @@ export interface Options {
confirmStyle: Object, // Styles object confirmStyle: Object, // Styles object
session_calling_peer_key: string, session_calling_peer_key: string,
config: RTCConfiguration, config: RTCConfiguration,
__messages_per_send?: number,
} }
enum CallingState { enum CallingState {
@ -23,7 +24,7 @@ enum CallingState {
False, False,
}; };
//@ts-ignore peerjs hack for webpack5 (?!) //@ts-ignore peerjs hack for webpack5 (?!) TODO: ES/node modules;
Peer = Peer.default || Peer; Peer = Peer.default || Peer;
// type IncomeMessages = // type IncomeMessages =
@ -32,13 +33,13 @@ Peer = Peer.default || Peer;
// { type: "click", x: number, y: number } | // { type: "click", x: number, y: number } |
// { x: number, y: number } // { x: number, y: number }
export default function(opts: Partial<Options> = {}) { export default function(opts?: Partial<Options>) {
const options: Options = Object.assign( const options: Options = Object.assign(
{ {
confirmText: "You have an incoming call. Do you want to answer?", confirmText: "You have an incoming call. Do you want to answer?",
confirmStyle: {}, confirmStyle: {},
session_calling_peer_key: "__openreplay_calling_peer", session_calling_peer_key: "__openreplay_calling_peer",
config: null config: null,
}, },
opts, opts,
); );
@ -58,6 +59,7 @@ export default function(opts: Partial<Options> = {}) {
let assistDemandedRestart = false let assistDemandedRestart = false
let peer : Peer | null = null 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> = {} const openDataConnections: Record<string, BufferingConnection> = {}
app.addCommitCallback(function(messages) { app.addCommitCallback(function(messages) {
@ -66,7 +68,10 @@ export default function(opts: Partial<Options> = {}) {
app.attachStopCallback(function() { app.attachStopCallback(function() {
if (assistDemandedRestart) { return; } if (assistDemandedRestart) { return; }
peer && peer.destroy(); if (peer) {
peer.destroy();
log('Peer destroyed!')
}
}); });
app.attachStartCallback(function() { app.attachStartCallback(function() {
@ -77,6 +82,7 @@ export default function(opts: Partial<Options> = {}) {
host: app.getHost(), host: app.getHost(),
path: '/assist', path: '/assist',
port: location.protocol === 'http:' && appOptions.__DISABLE_SECURE_MODE ? 80 : 443, port: location.protocol === 'http:' && appOptions.__DISABLE_SECURE_MODE ? 80 : 443,
//debug: // 0 Print nothing //1 Prints only errors. / 2 Prints errors and warnings. / 3 Prints all logs.
} }
if (options.config) { if (options.config) {
_opt['config'] = options.config _opt['config'] = options.config
@ -92,7 +98,7 @@ export default function(opts: Partial<Options> = {}) {
log('Connection opened.') log('Connection opened.')
assistDemandedRestart = true; assistDemandedRestart = true;
app.stop(); app.stop();
openDataConnections[conn.peer] = new BufferingConnection(conn) openDataConnections[conn.peer] = new BufferingConnection(conn, options.__messages_per_send)
conn.on('close', () => { conn.on('close', () => {
log("Connection close: ", conn.peer) log("Connection close: ", conn.peer)
delete openDataConnections[conn.peer] // TODO: check if works properly delete openDataConnections[conn.peer] // TODO: check if works properly
@ -206,6 +212,26 @@ export default function(opts: Partial<Options> = {}) {
log("name recieved: ", data) log("name recieved: ", data)
callUI.setAssistentName(data.name); callUI.setAssistentName(data.name);
} }
if (data.type === "scroll" && Array.isArray(data.delta)) {
const scrEl = document.scrollingElement || document.documentElement
const [mouseX, mouseY] = mouse.getPosition()
const [dX, dY] = data.delta;
const el = document.elementFromPoint(mouseX-scrEl.scrollLeft, mouseY-scrEl.scrollTop)
let scrolled = false // what would be the browser-like logic?
if (el) {
if(el.scrollWidth > el.clientWidth) {
el.scrollLeft += data.delta[0]
scrolled = true
}
if (el && el.scrollHeight > el.clientHeight) {
el.scrollTop += data.delta[1]
scrolled = true
}
}
if (!scrolled) {
window.scroll(scrEl.scrollLeft + data.delta[0], scrEl.scrollTop + data.delta[1])
}
}
if (data.type === "click" && typeof data.x === 'number' && typeof data.y === 'number') { if (data.type === "click" && typeof data.x === 'number' && typeof data.y === 'number') {
const el = document.elementFromPoint(data.x, data.y) const el = document.elementFromPoint(data.x, data.y)
if (el instanceof HTMLElement) { if (el instanceof HTMLElement) {