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 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 {
|
||||
userId: String,
|
||||
toggleChatWindow: (state) => void,
|
||||
|
|
@ -32,18 +45,6 @@ function AssistActions({ toggleChatWindow, userId, calling, 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) {
|
||||
setLocalStream(lStream);
|
||||
setEndCall(() => callPeer(
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { update, getState } from '../../store';
|
|||
|
||||
|
||||
export enum CallingState {
|
||||
Reconnecting,
|
||||
Requesting,
|
||||
True,
|
||||
False,
|
||||
|
|
@ -38,7 +39,7 @@ export function getStatusText(status: ConnectionStatus): string {
|
|||
case ConnectionStatus.Error:
|
||||
return "Something went wrong. Try to reload the page.";
|
||||
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});
|
||||
conn.on('open', () => {
|
||||
window.addEventListener("beforeunload", ()=>conn.open &&conn.send("unload"));
|
||||
|
||||
//console.log("peer connected")
|
||||
|
||||
|
||||
if (getState().calling === CallingState.Reconnecting) {
|
||||
this._call()
|
||||
}
|
||||
|
||||
let i = 0;
|
||||
let firstMessage = true;
|
||||
|
|
@ -195,7 +203,7 @@ export default class AssistManager {
|
|||
|
||||
conn.on('data', (data) => {
|
||||
if (!Array.isArray(data)) { return this.handleCommand(data); }
|
||||
this.mesagesRecieved = true;
|
||||
this.disconnectTimeout && clearTimeout(this.disconnectTimeout);
|
||||
if (firstMessage) {
|
||||
firstMessage = false;
|
||||
this.setStatus(ConnectionStatus.Connected)
|
||||
|
|
@ -246,8 +254,8 @@ export default class AssistManager {
|
|||
|
||||
|
||||
const onDataClose = () => {
|
||||
this.initiateCallEnd();
|
||||
this.setStatus(ConnectionStatus.Connecting);
|
||||
this.onCallDisconnect()
|
||||
//console.log('closed peer conn. Reconnecting...')
|
||||
this.connectToPeer();
|
||||
}
|
||||
|
||||
|
|
@ -276,8 +284,6 @@ export default class AssistManager {
|
|||
}
|
||||
|
||||
|
||||
private onCallEnd: null | (()=>void) = null;
|
||||
private onReject: null | (()=>void) = null;
|
||||
private forceCallEnd() {
|
||||
this.callConnection?.close();
|
||||
}
|
||||
|
|
@ -290,33 +296,37 @@ export default class AssistManager {
|
|||
private initiateCallEnd = () => {
|
||||
this.forceCallEnd();
|
||||
this.notifyCallEnd();
|
||||
this.onCallEnd?.();
|
||||
this.localCallData && this.localCallData.onCallEnd();
|
||||
}
|
||||
|
||||
private onTrackerCallEnd = () => {
|
||||
console.log('onTrackerCallEnd')
|
||||
this.forceCallEnd();
|
||||
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 mesagesRecieved: boolean = false;
|
||||
private disconnectTimeout: ReturnType<typeof setTimeout> | undefined;
|
||||
private handleCommand(command: string) {
|
||||
console.log("Data command", command)
|
||||
switch (command) {
|
||||
case "unload":
|
||||
this.onTrackerCallEnd();
|
||||
this.mesagesRecieved = false;
|
||||
setTimeout(() => {
|
||||
if (this.mesagesRecieved) {
|
||||
return;
|
||||
}
|
||||
// @ts-ignore
|
||||
this.dataConnection?.close();
|
||||
//this.onTrackerCallEnd();
|
||||
this.onCallDisconnect()
|
||||
this.dataConnection?.close();
|
||||
this.disconnectTimeout = setTimeout(() => {
|
||||
this.onTrackerCallEnd();
|
||||
this.setStatus(ConnectionStatus.Disconnected);
|
||||
}, 8000); // TODO: more convenient way
|
||||
}, 15000); // TODO: more convenient way
|
||||
//this.dataConnection?.close();
|
||||
return;
|
||||
case "call_end":
|
||||
|
|
@ -337,60 +347,67 @@ export default class AssistManager {
|
|||
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 {
|
||||
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 });
|
||||
|
||||
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 });
|
||||
onStream(stream);
|
||||
this.localCallData && this.localCallData.onStream(stream);
|
||||
this.send({
|
||||
name: store.getState().getIn([ 'user', 'account', 'name']),
|
||||
});
|
||||
|
||||
// @ts-ignore ??
|
||||
this.md.overlay.addEventListener("mousemove", this.onMouseMove)
|
||||
});
|
||||
|
||||
this.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("close", this.localCallData.onCallEnd);
|
||||
call.on("error", (e) => {
|
||||
console.error("PeerJS error (on call):", e)
|
||||
this.initiateCallEnd?.();
|
||||
onError?.();
|
||||
this.initiateCallEnd();
|
||||
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)
|
||||
|
||||
return this.initiateCallEnd;
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.initiateCallEnd();
|
||||
this.dataCheckIntervalID && clearInterval(this.dataCheckIntervalID);
|
||||
if (this.peer) {
|
||||
this.peer.connections[this.peerID]?.forEach(c => c.open && c.close());
|
||||
this.peer.disconnect();
|
||||
this.peer.destroy();
|
||||
//console.log("destroying peer...")
|
||||
const peer = this.peer; // otherwise it calls reconnection on data chan close
|
||||
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