From 2ebdd3d67ff1c0ba872417db06aa813b34d34eb7 Mon Sep 17 00:00:00 2001 From: ShiKhu Date: Thu, 23 Sep 2021 18:04:26 +0200 Subject: [PATCH] feat (frontend): re-call peer on remote page reload --- .../AssistActions/AssistActions.tsx | 25 ++-- .../managers/AssistManager.ts | 117 ++++++++++-------- .../managers/StylesManager.js | 92 -------------- 3 files changed, 80 insertions(+), 154 deletions(-) delete mode 100644 frontend/app/player/MessageDistributor/managers/StylesManager.js diff --git a/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx b/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx index 0d51cca91..1c5af3090 100644 --- a/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx +++ b/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx @@ -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( diff --git a/frontend/app/player/MessageDistributor/managers/AssistManager.ts b/frontend/app/player/MessageDistributor/managers/AssistManager.ts index ea2121464..7e6dce18d 100644 --- a/frontend/app/player/MessageDistributor/managers/AssistManager.ts +++ b/frontend/app/player/MessageDistributor/managers/AssistManager.ts @@ -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 | 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(); } } } diff --git a/frontend/app/player/MessageDistributor/managers/StylesManager.js b/frontend/app/player/MessageDistributor/managers/StylesManager.js deleted file mode 100644 index 9ae18fc83..000000000 --- a/frontend/app/player/MessageDistributor/managers/StylesManager.js +++ /dev/null @@ -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 { - #screen: StatedScreen; - _linkLoadingCount: number = 0; - _linkLoadPromises: Array> = []; - _skipCSSLinks: Array = []; // 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 { - return Promise.all(this._linkLoadPromises) - .then(() => this.moveApply(t, this.#manageRule)); - } -} \ No newline at end of file