feat (frontend): re-call peer on remote page reload
This commit is contained in:
parent
7b5d21a220
commit
2ebdd3d67f
3 changed files with 80 additions and 154 deletions
|
|
@ -10,6 +10,19 @@ import { CallingState, ConnectionStatus } from 'Player/MessageDistributor/manage
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import stl from './AassistActions.css'
|
import stl from './AassistActions.css'
|
||||||
|
|
||||||
|
function onClose(stream) {
|
||||||
|
stream.getTracks().forEach(t=>t.stop());
|
||||||
|
}
|
||||||
|
|
||||||
|
function onReject() {
|
||||||
|
toast.info(`Call was rejected.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onError(e) {
|
||||||
|
toast.error(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
userId: String,
|
userId: String,
|
||||||
toggleChatWindow: (state) => void,
|
toggleChatWindow: (state) => void,
|
||||||
|
|
@ -32,18 +45,6 @@ function AssistActions({ toggleChatWindow, userId, calling, peerConnectionStatus
|
||||||
}
|
}
|
||||||
}, [peerConnectionStatus])
|
}, [peerConnectionStatus])
|
||||||
|
|
||||||
function onClose(stream) {
|
|
||||||
stream.getTracks().forEach(t=>t.stop());
|
|
||||||
}
|
|
||||||
|
|
||||||
function onReject() {
|
|
||||||
toast.info(`Call was rejected.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onError(e) {
|
|
||||||
toast.error(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onCallConnect(lStream) {
|
function onCallConnect(lStream) {
|
||||||
setLocalStream(lStream);
|
setLocalStream(lStream);
|
||||||
setEndCall(() => callPeer(
|
setEndCall(() => callPeer(
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { update, getState } from '../../store';
|
||||||
|
|
||||||
|
|
||||||
export enum CallingState {
|
export enum CallingState {
|
||||||
|
Reconnecting,
|
||||||
Requesting,
|
Requesting,
|
||||||
True,
|
True,
|
||||||
False,
|
False,
|
||||||
|
|
@ -38,7 +39,7 @@ export function getStatusText(status: ConnectionStatus): string {
|
||||||
case ConnectionStatus.Error:
|
case ConnectionStatus.Error:
|
||||||
return "Something went wrong. Try to reload the page.";
|
return "Something went wrong. Try to reload the page.";
|
||||||
case ConnectionStatus.WaitingMessages:
|
case ConnectionStatus.WaitingMessages:
|
||||||
return "Connected. Waiting for the data..."
|
return "Connected. Waiting for the data... (The tab might be inactive)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -187,6 +188,13 @@ export default class AssistManager {
|
||||||
const conn = this.peer.connect(id, { serialization: 'json', reliable: true});
|
const conn = this.peer.connect(id, { serialization: 'json', reliable: true});
|
||||||
conn.on('open', () => {
|
conn.on('open', () => {
|
||||||
window.addEventListener("beforeunload", ()=>conn.open &&conn.send("unload"));
|
window.addEventListener("beforeunload", ()=>conn.open &&conn.send("unload"));
|
||||||
|
|
||||||
|
//console.log("peer connected")
|
||||||
|
|
||||||
|
|
||||||
|
if (getState().calling === CallingState.Reconnecting) {
|
||||||
|
this._call()
|
||||||
|
}
|
||||||
|
|
||||||
let i = 0;
|
let i = 0;
|
||||||
let firstMessage = true;
|
let firstMessage = true;
|
||||||
|
|
@ -195,7 +203,7 @@ export default class AssistManager {
|
||||||
|
|
||||||
conn.on('data', (data) => {
|
conn.on('data', (data) => {
|
||||||
if (!Array.isArray(data)) { return this.handleCommand(data); }
|
if (!Array.isArray(data)) { return this.handleCommand(data); }
|
||||||
this.mesagesRecieved = true;
|
this.disconnectTimeout && clearTimeout(this.disconnectTimeout);
|
||||||
if (firstMessage) {
|
if (firstMessage) {
|
||||||
firstMessage = false;
|
firstMessage = false;
|
||||||
this.setStatus(ConnectionStatus.Connected)
|
this.setStatus(ConnectionStatus.Connected)
|
||||||
|
|
@ -246,8 +254,8 @@ export default class AssistManager {
|
||||||
|
|
||||||
|
|
||||||
const onDataClose = () => {
|
const onDataClose = () => {
|
||||||
this.initiateCallEnd();
|
this.onCallDisconnect()
|
||||||
this.setStatus(ConnectionStatus.Connecting);
|
//console.log('closed peer conn. Reconnecting...')
|
||||||
this.connectToPeer();
|
this.connectToPeer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -276,8 +284,6 @@ export default class AssistManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private onCallEnd: null | (()=>void) = null;
|
|
||||||
private onReject: null | (()=>void) = null;
|
|
||||||
private forceCallEnd() {
|
private forceCallEnd() {
|
||||||
this.callConnection?.close();
|
this.callConnection?.close();
|
||||||
}
|
}
|
||||||
|
|
@ -290,33 +296,37 @@ export default class AssistManager {
|
||||||
private initiateCallEnd = () => {
|
private initiateCallEnd = () => {
|
||||||
this.forceCallEnd();
|
this.forceCallEnd();
|
||||||
this.notifyCallEnd();
|
this.notifyCallEnd();
|
||||||
this.onCallEnd?.();
|
this.localCallData && this.localCallData.onCallEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
private onTrackerCallEnd = () => {
|
private onTrackerCallEnd = () => {
|
||||||
|
console.log('onTrackerCallEnd')
|
||||||
this.forceCallEnd();
|
this.forceCallEnd();
|
||||||
if (getState().calling === CallingState.Requesting) {
|
if (getState().calling === CallingState.Requesting) {
|
||||||
this.onReject?.();
|
this.localCallData && this.localCallData.onReject();
|
||||||
|
}
|
||||||
|
this.localCallData && this.localCallData.onCallEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
private onCallDisconnect = () => {
|
||||||
|
if (getState().calling === CallingState.True) {
|
||||||
|
update({ calling: CallingState.Reconnecting });
|
||||||
}
|
}
|
||||||
this.onCallEnd?.();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private disconnectTimeout: ReturnType<typeof setTimeout> | undefined;
|
||||||
private mesagesRecieved: boolean = false;
|
|
||||||
private handleCommand(command: string) {
|
private handleCommand(command: string) {
|
||||||
|
console.log("Data command", command)
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case "unload":
|
case "unload":
|
||||||
this.onTrackerCallEnd();
|
//this.onTrackerCallEnd();
|
||||||
this.mesagesRecieved = false;
|
this.onCallDisconnect()
|
||||||
setTimeout(() => {
|
this.dataConnection?.close();
|
||||||
if (this.mesagesRecieved) {
|
this.disconnectTimeout = setTimeout(() => {
|
||||||
return;
|
this.onTrackerCallEnd();
|
||||||
}
|
|
||||||
// @ts-ignore
|
|
||||||
this.dataConnection?.close();
|
|
||||||
this.setStatus(ConnectionStatus.Disconnected);
|
this.setStatus(ConnectionStatus.Disconnected);
|
||||||
}, 8000); // TODO: more convenient way
|
}, 15000); // TODO: more convenient way
|
||||||
//this.dataConnection?.close();
|
//this.dataConnection?.close();
|
||||||
return;
|
return;
|
||||||
case "call_end":
|
case "call_end":
|
||||||
|
|
@ -337,60 +347,67 @@ export default class AssistManager {
|
||||||
conn.send({ x: Math.round(data.x), y: Math.round(data.y) });
|
conn.send({ x: Math.round(data.x), y: Math.round(data.y) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private localCallData: {
|
||||||
|
localStream: MediaStream,
|
||||||
|
onStream: (s: MediaStream)=>void,
|
||||||
|
onCallEnd: () => void,
|
||||||
|
onReject: () => void,
|
||||||
|
onError?: ()=> void
|
||||||
|
} | null = null
|
||||||
call(localStream: MediaStream, onStream: (s: MediaStream)=>void, onCallEnd: () => void, onReject: () => void, onError?: ()=> void): null | Function {
|
call(localStream: MediaStream, onStream: (s: MediaStream)=>void, onCallEnd: () => void, onReject: () => void, onError?: ()=> void): null | Function {
|
||||||
if (!this.peer || getState().calling !== CallingState.False) { return null; }
|
this.localCallData = {
|
||||||
|
localStream,
|
||||||
|
onStream,
|
||||||
|
onCallEnd: () => {
|
||||||
|
onCallEnd();
|
||||||
|
this.md.overlay.removeEventListener("mousemove", this.onMouseMove);
|
||||||
|
update({ calling: CallingState.False });
|
||||||
|
this.localCallData = null;
|
||||||
|
},
|
||||||
|
onReject,
|
||||||
|
onError,
|
||||||
|
}
|
||||||
|
this._call()
|
||||||
|
return this.initiateCallEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _call() {
|
||||||
|
if (!this.peer || !this.localCallData || ![CallingState.False, CallingState.Reconnecting].includes(getState().calling)) { return null; }
|
||||||
|
|
||||||
update({ calling: CallingState.Requesting });
|
update({ calling: CallingState.Requesting });
|
||||||
|
|
||||||
const call = this.peer.call(this.peerID, localStream);
|
|
||||||
call.on('stream', stream => {
|
|
||||||
//call.peerConnection.ontrack = (t)=> console.log('ontrack', t)
|
|
||||||
|
|
||||||
|
//console.log('calling...', this.localCallData.localStream)
|
||||||
|
|
||||||
|
const call = this.peer.call(this.peerID, this.localCallData.localStream);
|
||||||
|
call.on('stream', stream => {
|
||||||
update({ calling: CallingState.True });
|
update({ calling: CallingState.True });
|
||||||
onStream(stream);
|
this.localCallData && this.localCallData.onStream(stream);
|
||||||
this.send({
|
this.send({
|
||||||
name: store.getState().getIn([ 'user', 'account', 'name']),
|
name: store.getState().getIn([ 'user', 'account', 'name']),
|
||||||
});
|
});
|
||||||
|
|
||||||
// @ts-ignore ??
|
|
||||||
this.md.overlay.addEventListener("mousemove", this.onMouseMove)
|
this.md.overlay.addEventListener("mousemove", this.onMouseMove)
|
||||||
});
|
});
|
||||||
|
|
||||||
this.onCallEnd = () => {
|
call.on("close", this.localCallData.onCallEnd);
|
||||||
onCallEnd();
|
|
||||||
// @ts-ignore ??
|
|
||||||
this.md.overlay.removeEventListener("mousemove", this.onMouseMove);
|
|
||||||
update({ calling: CallingState.False });
|
|
||||||
this.onCallEnd = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
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.initiateCallEnd?.();
|
this.initiateCallEnd();
|
||||||
onError?.();
|
this.localCallData && this.localCallData.onError && this.localCallData.onError();
|
||||||
});
|
});
|
||||||
|
|
||||||
// const intervalID = setInterval(() => {
|
|
||||||
// if (!call.open && getState().calling === CallingState.True) {
|
|
||||||
// this.onCallEnd?.();
|
|
||||||
// clearInterval(intervalID);
|
|
||||||
// }
|
|
||||||
// }, 5000);
|
|
||||||
|
|
||||||
window.addEventListener("beforeunload", this.initiateCallEnd)
|
window.addEventListener("beforeunload", this.initiateCallEnd)
|
||||||
|
|
||||||
return this.initiateCallEnd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
this.initiateCallEnd();
|
this.initiateCallEnd();
|
||||||
this.dataCheckIntervalID && clearInterval(this.dataCheckIntervalID);
|
this.dataCheckIntervalID && clearInterval(this.dataCheckIntervalID);
|
||||||
if (this.peer) {
|
if (this.peer) {
|
||||||
this.peer.connections[this.peerID]?.forEach(c => c.open && c.close());
|
//console.log("destroying peer...")
|
||||||
this.peer.disconnect();
|
const peer = this.peer; // otherwise it calls reconnection on data chan close
|
||||||
this.peer.destroy();
|
|
||||||
this.peer = null;
|
this.peer = null;
|
||||||
|
peer.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import type StatedScreen from '../StatedScreen';
|
|
||||||
import type { CssInsertRule, CssDeleteRule } from '../messages';
|
|
||||||
import type { Timed } from '../Timed';
|
|
||||||
|
|
||||||
type CSSRuleMessage = CssInsertRule | CssDeleteRule;
|
|
||||||
type TimedCSSRuleMessage = Timed & CSSRuleMessage;
|
|
||||||
|
|
||||||
import logger from 'App/logger';
|
|
||||||
import ListWalker from './ListWalker';
|
|
||||||
|
|
||||||
export default class StylesManager extends ListWalker<TimedCSSRuleMessage> {
|
|
||||||
#screen: StatedScreen;
|
|
||||||
_linkLoadingCount: number = 0;
|
|
||||||
_linkLoadPromises: Array<Promise<void>> = [];
|
|
||||||
_skipCSSLinks: Array<string> = []; // should be common for all pages
|
|
||||||
|
|
||||||
constructor(screen: StatedScreen) {
|
|
||||||
super();
|
|
||||||
this.#screen = screen;
|
|
||||||
}
|
|
||||||
|
|
||||||
reset():void {
|
|
||||||
super.reset();
|
|
||||||
this._linkLoadingCount = 0;
|
|
||||||
this._linkLoadPromises = [];
|
|
||||||
|
|
||||||
//cancel all promises? tothinkaboutit
|
|
||||||
}
|
|
||||||
|
|
||||||
setStyleHandlers(node: HTMLLinkElement, value: string): void {
|
|
||||||
let timeoutId;
|
|
||||||
const promise = new Promise((resolve) => {
|
|
||||||
if (this._skipCSSLinks.includes(value)) resolve();
|
|
||||||
this._linkLoadingCount++;
|
|
||||||
this.#screen.setCSSLoading(true);
|
|
||||||
const setSkipAndResolve = () => {
|
|
||||||
this._skipCSSLinks.push(value); // watch out
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
timeoutId = setTimeout(setSkipAndResolve, 4000);
|
|
||||||
|
|
||||||
node.onload = resolve;
|
|
||||||
node.onerror = setSkipAndResolve;
|
|
||||||
}).then(() => {
|
|
||||||
node.onload = null;
|
|
||||||
node.onerror = null;
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
this._linkLoadingCount--;
|
|
||||||
if (this._linkLoadingCount === 0) {
|
|
||||||
this.#screen.setCSSLoading(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this._linkLoadPromises.push(promise);
|
|
||||||
}
|
|
||||||
|
|
||||||
#manageRule = (msg: CSSRuleMessage):void => {
|
|
||||||
// if (msg.tp === "css_insert_rule") {
|
|
||||||
// let styleSheet = this.#screen.document.styleSheets[ msg.stylesheetID ];
|
|
||||||
// if (!styleSheet) {
|
|
||||||
// logger.log("No stylesheet with corresponding ID found: ", msg)
|
|
||||||
// styleSheet = this.#screen.document.styleSheets[0];
|
|
||||||
// if (!styleSheet) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// try {
|
|
||||||
// styleSheet.insertRule(msg.rule, msg.index);
|
|
||||||
// } catch (e) {
|
|
||||||
// logger.log(e, msg)
|
|
||||||
// //const index = Math.min(msg.index, styleSheet.cssRules.length);
|
|
||||||
// styleSheet.insertRule(msg.rule, styleSheet.cssRules.length);
|
|
||||||
// //styleSheet.ownerNode.innerHTML += msg.rule;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (msg.tp === "css_delete_rule") {
|
|
||||||
// // console.warn('Warning: STYLESHEET_DELETE_RULE msg')
|
|
||||||
// const styleSheet = this.#screen.document.styleSheets[msg.stylesheetID];
|
|
||||||
// if (!styleSheet) {
|
|
||||||
// logger.log("No stylesheet with corresponding ID found: ", msg)
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// styleSheet.deleteRule(msg.index);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
moveReady(t: number): Promise<void> {
|
|
||||||
return Promise.all(this._linkLoadPromises)
|
|
||||||
.then(() => this.moveApply(t, this.#manageRule));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Reference in a new issue