fix (tracker-assist & frontend-assist): connection logic fix
This commit is contained in:
parent
bedcf9dd08
commit
2e77aa3ca7
3 changed files with 113 additions and 37 deletions
|
|
@ -14,14 +14,26 @@ export enum CallingState {
|
||||||
False,
|
False,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export enum ConnectionStatus {
|
||||||
|
Connecting,
|
||||||
|
Connected,
|
||||||
|
Inactive,
|
||||||
|
Disconnected,
|
||||||
|
Error,
|
||||||
|
};
|
||||||
|
|
||||||
export interface State {
|
export interface State {
|
||||||
calling: CallingState,
|
calling: CallingState,
|
||||||
|
peerConnectionStatus: ConnectionStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const INITIAL_STATE: State = {
|
export const INITIAL_STATE: State = {
|
||||||
calling: CallingState.False,
|
calling: CallingState.False,
|
||||||
|
peerConnectionStatus: ConnectionStatus.Connecting,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MAX_RECONNECTION_COUNT = 6;
|
||||||
|
|
||||||
|
|
||||||
function resolveURL(baseURL: string, relURL: string): string {
|
function resolveURL(baseURL: string, relURL: string): string {
|
||||||
if (relURL.startsWith('#') || relURL === "") {
|
if (relURL.startsWith('#') || relURL === "") {
|
||||||
|
|
@ -90,6 +102,7 @@ export default class AssistManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private peer: Peer | null = null;
|
private peer: Peer | null = null;
|
||||||
|
connectionAttempts: number = 0;
|
||||||
connect() {
|
connect() {
|
||||||
if (this.peer != null) {
|
if (this.peer != null) {
|
||||||
console.error("AssistManager: trying to connect more than once");
|
console.error("AssistManager: trying to connect more than once");
|
||||||
|
|
@ -107,9 +120,16 @@ export default class AssistManager {
|
||||||
this.peer = peer;
|
this.peer = peer;
|
||||||
this.peer.on('error', e => {
|
this.peer.on('error', e => {
|
||||||
if (e.type === 'peer-unavailable') {
|
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 {
|
} else {
|
||||||
console.error(`PeerJS error (on peer). Type ${e.type}`, e);
|
console.error(`PeerJS error (on peer). Type ${e.type}`, e);
|
||||||
|
update({ peerConnectionStatus: ConnectionStatus.Error })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
peer.on("open", me => {
|
peer.on("open", me => {
|
||||||
|
|
@ -126,13 +146,20 @@ export default class AssistManager {
|
||||||
const conn = this.peer.connect(id, { serialization: 'json'});
|
const conn = this.peer.connect(id, { serialization: 'json'});
|
||||||
|
|
||||||
conn.on('open', () => {
|
conn.on('open', () => {
|
||||||
this.md.setMessagesLoading(false);
|
update({ peerConnectionStatus: ConnectionStatus.Inactive });
|
||||||
let i = 0;
|
|
||||||
console.log("peer connected")
|
console.log("peer connected")
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
let firstMessage = true;
|
||||||
conn.on('data', (data) => {
|
conn.on('data', (data) => {
|
||||||
if (typeof data === 'string') { return this.handleCommand(data); }
|
if (typeof data === 'string') { return this.handleCommand(data); }
|
||||||
if (!Array.isArray(data)) { return; }
|
if (!Array.isArray(data)) { return; }
|
||||||
|
if (firstMessage) {
|
||||||
|
firstMessage = false;
|
||||||
|
this.md.setMessagesLoading(false);
|
||||||
|
update({ peerConnectionStatus: ConnectionStatus.Connected })
|
||||||
|
}
|
||||||
|
|
||||||
let time = 0;
|
let time = 0;
|
||||||
let ts0 = 0;
|
let ts0 = 0;
|
||||||
(data as Array<Message & { _id: number}>).forEach(msg => {
|
(data as Array<Message & { _id: number}>).forEach(msg => {
|
||||||
|
|
@ -174,38 +201,58 @@ export default class AssistManager {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
conn.on('close', () => {
|
conn.on('close', () => this.onDataClose());// Doesn't work ?
|
||||||
this.md.setMessagesLoading(true);
|
|
||||||
this.endCall();
|
|
||||||
console.log('closed peer conn. Reconnecting...')
|
|
||||||
setTimeout(() => this.connectToPeer(), 300); // reconnect
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 onCallEnd: null | (()=>void) = null;
|
||||||
private endCall = () => {
|
private assistentCallEnd = () => {
|
||||||
const conn = this.callConnection;
|
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?.();
|
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) {
|
private handleCommand(command: string) {
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case "call_end":
|
case "call_end":
|
||||||
console.log("Call end recieved")
|
this.onTrackerCallEnd();
|
||||||
this.endCall();
|
return;
|
||||||
|
case "call_error":
|
||||||
|
this.onTrackerCallEnd();
|
||||||
|
update({ peerConnectionStatus: ConnectionStatus.Error });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -247,18 +294,23 @@ export default class AssistManager {
|
||||||
update({ calling: CallingState.False });
|
update({ calling: CallingState.False });
|
||||||
this.onCallEnd = null;
|
this.onCallEnd = null;
|
||||||
}
|
}
|
||||||
call.on("close", this.onCallEnd);
|
//call.on("close", this.onCallEnd);
|
||||||
call.on("error", (e) => {
|
call.on("error", (e) => {
|
||||||
console.error("PeerJS error (on call):", e)
|
console.error("PeerJS error (on call):", e)
|
||||||
this.onCallEnd?.();
|
this.onCallEnd?.();
|
||||||
onError?.();
|
onError?.();
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.endCall;
|
window.addEventListener("beforeunload", this.assistentCallEnd)
|
||||||
|
|
||||||
|
return this.assistentCallEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
|
this.assistentCallEnd();
|
||||||
|
console.log("destroying peer...")
|
||||||
this.peer?.destroy();
|
this.peer?.destroy();
|
||||||
|
this.peer = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
|
|
||||||
const declineIcon = `<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 128 128" ><g id="Circle_Grid" data-name="Circle Grid"><circle cx="64" cy="64" fill="#ef5261" r="64"/></g><g id="icon"><path d="m57.831 70.1c8.79 8.79 17.405 12.356 20.508 9.253l4.261-4.26a7.516 7.516 0 0 1 10.629 0l9.566 9.566a7.516 7.516 0 0 1 0 10.629l-7.453 7.453c-7.042 7.042-27.87-2.358-47.832-22.319-9.976-9.981-16.519-19.382-20.748-28.222s-5.086-16.091-1.567-19.61l7.453-7.453a7.516 7.516 0 0 1 10.629 0l9.566 9.563a7.516 7.516 0 0 1 0 10.629l-4.264 4.271c-3.103 3.1.462 11.714 9.252 20.5z" fill="#eeefee"/></g></svg>`;
|
const declineIcon = `<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 128 128" ><g id="Circle_Grid" data-name="Circle Grid"><circle cx="64" cy="64" fill="#ef5261" r="64"/></g><g id="icon"><path d="m57.831 70.1c8.79 8.79 17.405 12.356 20.508 9.253l4.261-4.26a7.516 7.516 0 0 1 10.629 0l9.566 9.566a7.516 7.516 0 0 1 0 10.629l-7.453 7.453c-7.042 7.042-27.87-2.358-47.832-22.319-9.976-9.981-16.519-19.382-20.748-28.222s-5.086-16.091-1.567-19.61l7.453-7.453a7.516 7.516 0 0 1 10.629 0l9.566 9.563a7.516 7.516 0 0 1 0 10.629l-4.264 4.271c-3.103 3.1.462 11.714 9.252 20.5z" fill="#eeefee"/></g></svg>`;
|
||||||
|
|
||||||
export default function confirm(text: string, styles?: Object): Promise<boolean> {
|
export default class Confirm {
|
||||||
return new Promise(resolve => {
|
private wrapper: HTMLDivElement;
|
||||||
|
|
||||||
|
constructor(text: string, styles?: Object) {
|
||||||
const wrapper = document.createElement('div');
|
const wrapper = document.createElement('div');
|
||||||
const popup = document.createElement('div');
|
const popup = document.createElement('div');
|
||||||
const p = document.createElement('p');
|
const p = document.createElement('p');
|
||||||
|
|
@ -60,17 +61,30 @@ export default function confirm(text: string, styles?: Object): Promise<boolean>
|
||||||
pointerEvents: "none",
|
pointerEvents: "none",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
wrapper.appendChild(popup);
|
wrapper.appendChild(popup);
|
||||||
document.body.appendChild(wrapper);
|
this.wrapper = wrapper;
|
||||||
|
|
||||||
answerBtn.onclick = () => {
|
answerBtn.onclick = () => {
|
||||||
document.body.removeChild(wrapper);
|
this.remove();
|
||||||
resolve(true);
|
this.callback(true);
|
||||||
}
|
}
|
||||||
declineBtn.onclick = () => {
|
declineBtn.onclick = () => {
|
||||||
document.body.removeChild(wrapper);
|
this.remove();
|
||||||
resolve(false);
|
this.callback(false);
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,7 +5,7 @@ import type Message from '@openreplay/tracker';
|
||||||
|
|
||||||
import Mouse from './Mouse';
|
import Mouse from './Mouse';
|
||||||
import CallWindow from './CallWindow';
|
import CallWindow from './CallWindow';
|
||||||
import confirm from './confirm';
|
import Confirm from './Confirm';
|
||||||
|
|
||||||
|
|
||||||
export interface Options {
|
export interface Options {
|
||||||
|
|
@ -61,10 +61,20 @@ export default function(opts: Partial<Options> = {}) {
|
||||||
.connections[call.peer].find(c => c.type === 'data');
|
.connections[call.peer].find(c => c.type === 'data');
|
||||||
if (calling || !dataConn) {
|
if (calling || !dataConn) {
|
||||||
call.close();
|
call.close();
|
||||||
dataConn?.send("call_end");
|
dataConn?.send("call_error");
|
||||||
return;
|
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) {
|
if (!conf || !dataConn.open) {
|
||||||
call.close();
|
call.close();
|
||||||
dataConn.open && dataConn.send("call_end");
|
dataConn.open && dataConn.send("call_end");
|
||||||
|
|
@ -80,7 +90,7 @@ export default function(opts: Partial<Options> = {}) {
|
||||||
const onClose = () => {
|
const onClose = () => {
|
||||||
console.log("close call...")
|
console.log("close call...")
|
||||||
if (call.open) { call.close(); }
|
if (call.open) { call.close(); }
|
||||||
mouse?.remove();
|
mouse.remove();
|
||||||
callUI?.remove();
|
callUI?.remove();
|
||||||
oStream.getTracks().forEach(t => t.stop());
|
oStream.getTracks().forEach(t => t.stop());
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue