From 2e77aa3ca7358d97ee4e32e0ee0bcfd36285ae8a Mon Sep 17 00:00:00 2001 From: ShiKhu Date: Wed, 7 Jul 2021 18:06:01 +0300 Subject: [PATCH] fix (tracker-assist & frontend-assist): connection logic fix --- .../managers/AssistManager.ts | 98 ++++++++++++++----- tracker/tracker-assist/src/confirm.ts | 34 +++++-- tracker/tracker-assist/src/index.ts | 18 +++- 3 files changed, 113 insertions(+), 37 deletions(-) diff --git a/frontend/app/player/MessageDistributor/managers/AssistManager.ts b/frontend/app/player/MessageDistributor/managers/AssistManager.ts index 1740b6b08..674f9261f 100644 --- a/frontend/app/player/MessageDistributor/managers/AssistManager.ts +++ b/frontend/app/player/MessageDistributor/managers/AssistManager.ts @@ -14,14 +14,26 @@ export enum CallingState { False, }; +export enum ConnectionStatus { + Connecting, + Connected, + Inactive, + Disconnected, + Error, +}; + export interface State { calling: CallingState, + peerConnectionStatus: ConnectionStatus, } export const INITIAL_STATE: State = { calling: CallingState.False, + peerConnectionStatus: ConnectionStatus.Connecting, } +const MAX_RECONNECTION_COUNT = 6; + function resolveURL(baseURL: string, relURL: string): string { if (relURL.startsWith('#') || relURL === "") { @@ -90,6 +102,7 @@ export default class AssistManager { } private peer: Peer | null = null; + connectionAttempts: number = 0; connect() { if (this.peer != null) { console.error("AssistManager: trying to connect more than once"); @@ -107,9 +120,16 @@ export default class AssistManager { this.peer = peer; this.peer.on('error', e => { if (e.type === 'peer-unavailable') { - this.connectToPeer(); // TODO: MAX_ATTEMPT_TIME + if (this.peer && this.connectionAttempts++ < MAX_RECONNECTION_COUNT) { + update({ peerConnectionStatus: ConnectionStatus.Connecting }) + this.connectToPeer(); + } else { + update({ peerConnectionStatus: ConnectionStatus.Disconnected }) + + } } else { console.error(`PeerJS error (on peer). Type ${e.type}`, e); + update({ peerConnectionStatus: ConnectionStatus.Error }) } }) peer.on("open", me => { @@ -126,13 +146,20 @@ export default class AssistManager { const conn = this.peer.connect(id, { serialization: 'json'}); conn.on('open', () => { - this.md.setMessagesLoading(false); - let i = 0; + update({ peerConnectionStatus: ConnectionStatus.Inactive }); console.log("peer connected") - + + let i = 0; + let firstMessage = true; conn.on('data', (data) => { if (typeof data === 'string') { return this.handleCommand(data); } if (!Array.isArray(data)) { return; } + if (firstMessage) { + firstMessage = false; + this.md.setMessagesLoading(false); + update({ peerConnectionStatus: ConnectionStatus.Connected }) + } + let time = 0; let ts0 = 0; (data as Array).forEach(msg => { @@ -174,38 +201,58 @@ export default class AssistManager { }); }); }); - conn.on('close', () => { - this.md.setMessagesLoading(true); - this.endCall(); - console.log('closed peer conn. Reconnecting...') - setTimeout(() => this.connectToPeer(), 300); // reconnect - }); + conn.on('close', () => this.onDataClose());// Doesn't work ? } - private get dataConnection(): DataConnection | null { - return this.peer?.connections[this.peerID]?.[0] || null; + + private onDataClose() { + this.md.setMessagesLoading(true); + this.assistentCallEnd(); + console.log('closed peer conn. Reconnecting...') + setTimeout(() => this.connectToPeer(), 0); // reconnect } - private get callConnection(): MediaConnection | null { - return this.peer?.connections[this.peerID]?.[1] || null; + + private get dataConnection(): DataConnection | undefined { + return this.peer?.connections[this.peerID]?.find(c => c.type === 'data' && c.open); + } + + private get callConnection(): MediaConnection | undefined { + return this.peer?.connections[this.peerID]?.find(c => c.type === 'media' && c.open); } private onCallEnd: null | (()=>void) = null; - private endCall = () => { - const conn = this.callConnection; + private assistentCallEnd = () => { + console.log('assistentCallEnd') + const conn = this.callConnection?.close(); + const dataConn = this.dataConnection; + if (dataConn) { + console.log("call_end send") + dataConn.send("call_end"); + } this.onCallEnd?.(); - if (!conn || !conn.open) { return; } - conn.close(); //calls onCallEnd twice - this.dataConnection?.send("call_end"); // } + private onTrackerCallEnd = () => { + const conn = this.callConnection; + if (conn && conn.open) { + conn.close(); + } + this.onCallEnd?.(); + } + + private handleCommand(command: string) { switch (command) { case "call_end": - console.log("Call end recieved") - this.endCall(); + this.onTrackerCallEnd(); + return; + case "call_error": + this.onTrackerCallEnd(); + update({ peerConnectionStatus: ConnectionStatus.Error }); + return; } } @@ -247,18 +294,23 @@ export default class AssistManager { update({ calling: CallingState.False }); this.onCallEnd = null; } - call.on("close", this.onCallEnd); + //call.on("close", this.onCallEnd); call.on("error", (e) => { console.error("PeerJS error (on call):", e) this.onCallEnd?.(); onError?.(); }); + + window.addEventListener("beforeunload", this.assistentCallEnd) - return this.endCall; + return this.assistentCallEnd; } clear() { + this.assistentCallEnd(); + console.log("destroying peer...") this.peer?.destroy(); + this.peer = null; } } diff --git a/tracker/tracker-assist/src/confirm.ts b/tracker/tracker-assist/src/confirm.ts index 54d628182..b5485ea86 100644 --- a/tracker/tracker-assist/src/confirm.ts +++ b/tracker/tracker-assist/src/confirm.ts @@ -1,9 +1,10 @@ const declineIcon = ``; -export default function confirm(text: string, styles?: Object): Promise { - return new Promise(resolve => { +export default class Confirm { + private wrapper: HTMLDivElement; + constructor(text: string, styles?: Object) { const wrapper = document.createElement('div'); const popup = document.createElement('div'); const p = document.createElement('p'); @@ -60,17 +61,30 @@ export default function confirm(text: string, styles?: Object): Promise pointerEvents: "none", }) - wrapper.appendChild(popup); - document.body.appendChild(wrapper); + this.wrapper = wrapper; answerBtn.onclick = () => { - document.body.removeChild(wrapper); - resolve(true); + this.remove(); + this.callback(true); } declineBtn.onclick = () => { - document.body.removeChild(wrapper); - resolve(false); + this.remove(); + this.callback(false); } - }) -} \ No newline at end of file + } + + mount() { + document.body.appendChild(this.wrapper); + } + + private callback: (result: boolean) => void = ()=>{}; + onAnswer(callback: (result: boolean) => void) { + this.callback = callback; + } + + remove() { + if (!this.wrapper.parentElement) { return; } + document.body.removeChild(this.wrapper); + } +} diff --git a/tracker/tracker-assist/src/index.ts b/tracker/tracker-assist/src/index.ts index c5d552f04..e89f74253 100644 --- a/tracker/tracker-assist/src/index.ts +++ b/tracker/tracker-assist/src/index.ts @@ -5,7 +5,7 @@ import type Message from '@openreplay/tracker'; import Mouse from './Mouse'; import CallWindow from './CallWindow'; -import confirm from './confirm'; +import Confirm from './Confirm'; export interface Options { @@ -61,10 +61,20 @@ export default function(opts: Partial = {}) { .connections[call.peer].find(c => c.type === 'data'); if (calling || !dataConn) { call.close(); - dataConn?.send("call_end"); + dataConn?.send("call_error"); return; } - confirm(options.confirmText, options.confirmStyle).then(conf => { + window.addEventListener("beforeunload", () => { + dataConn.open && dataConn.send("call_end"); + }); + dataConn.on('data', (data) => { // if call closed be a caller before confirm + if (data === "call_end") { + confirm.remove(); + } + }); + const confirm = new Confirm(options.confirmText, options.confirmStyle); + confirm.mount(); + confirm.onAnswer(conf => { if (!conf || !dataConn.open) { call.close(); dataConn.open && dataConn.send("call_end"); @@ -80,7 +90,7 @@ export default function(opts: Partial = {}) { const onClose = () => { console.log("close call...") if (call.open) { call.close(); } - mouse?.remove(); + mouse.remove(); callUI?.remove(); oStream.getTracks().forEach(t => t.stop());