From 41031c9f3769b04419f23d35e0bfe189dbc09545 Mon Sep 17 00:00:00 2001 From: Alex Kaminskii Date: Tue, 27 Dec 2022 00:32:53 +0100 Subject: [PATCH] refactor(player): move all live timeTravel logic to the WebLivePlayer --- frontend/app/player/web/MessageManager.ts | 66 ++++------------- frontend/app/player/web/WebLivePlayer.ts | 70 ++++++++++++++++--- .../app/player/web/assist/AssistManager.ts | 12 ++-- .../app/player/web/messages/MStreamReader.ts | 2 +- 4 files changed, 80 insertions(+), 70 deletions(-) diff --git a/frontend/app/player/web/MessageManager.ts b/frontend/app/player/web/MessageManager.ts index 8f0920eb4..0c52350d4 100644 --- a/frontend/app/player/web/MessageManager.ts +++ b/frontend/app/player/web/MessageManager.ts @@ -116,7 +116,6 @@ export default class MessageManager { private sessionStart: number; private navigationStartOffset: number = 0; private lastMessageTime: number = 0; - private lastMessageInFileTime: number = 0; constructor( private readonly session: any /*Session*/, @@ -142,17 +141,7 @@ export default class MessageManager { this.loadMessages() } - private parseAndDistributeMessages(fileReader: MFileReader, onMessage?: (msg: Message) => void) { - const msgs: Array = [] - for (let msg = fileReader.readNext();msg !== null;msg = fileReader.readNext()) { - this.distributeMessage(msg, msg._index) - msgs.push(msg) - onMessage?.(msg) - } - - logger.info("Messages count: ", msgs.length, msgs) - - + private _sortMessagesHack(msgs: Message[]) { // @ts-ignore Hack for upet (TODO: fix ordering in one mutation in tracker(removes first)) const headChildrenIds = msgs.filter(m => m.parentID === 1).map(m => m.id); this.pagesManager.sortPages((m1, m2) => { @@ -179,7 +168,6 @@ export default class MessageManager { }) } - private waitingForFiles: boolean = false private onFileReadSuccess = () => { const stateToUpdate : Partial= { @@ -199,10 +187,6 @@ export default class MessageManager { toast.error('Error requesting a session file') } private onFileReadFinally = () => { - this.incomingMessages - .filter(msg => msg.time >= this.lastMessageInFileTime) - .forEach(msg => this.distributeMessage(msg, 0)) - this.waitingForFiles = false this.setMessagesLoading(false) } @@ -217,7 +201,14 @@ export default class MessageManager { const fileReader = new MFileReader(new Uint8Array(), this.sessionStart) return (b: Uint8Array) => decrypt(b).then(b => { fileReader.append(b) - this.parseAndDistributeMessages(fileReader) + const msgs: Array = [] + for (let msg = fileReader.readNext();msg !== null;msg = fileReader.readNext()) { + this.distributeMessage(msg, msg._index) + msgs.push(msg) + } + + logger.info("Messages count: ", msgs.length, msgs) + this._sortMessagesHack(msgs) this.setMessagesLoading(false) }) } @@ -249,35 +240,14 @@ export default class MessageManager { .then(createNewParser(false)) ) .then(() => { - this.state.update(this.lists.getFullListsState()) + this.state.update(this.lists.getFullListsState()) // TODO: also in case of dynamic update through assist }) .catch(e => logger.error("Can not download the devtools file", e)) .finally(() => this.state.update({ devtoolsLoading: false })) } } - reloadWithUnprocessedFile(onSuccess: () => void) { - const onData = (byteArray: Uint8Array) => { - const onMessage = (msg: Message) => { this.lastMessageInFileTime = msg.time } - this.parseAndDistributeMessages(new MFileReader(byteArray, this.sessionStart), onMessage) - } - - // assist will pause and skip messages to prevent timestamp related errors - this.reloadMessageManagers() - this.windowNodeCounter.reset() - - this.setMessagesLoading(true) - this.waitingForFiles = true - - return requestEFSDom(this.session.sessionId) - .then(onData) - .then(onSuccess) - .then(this.onFileReadSuccess) - .catch(this.onFileReadFailed) - .finally(this.onFileReadFinally) - } - - private reloadMessageManagers() { + resetMessageManagers() { this.locationEventManager = new ListWalker(); this.locationManager = new ListWalker(); this.loadedLocationManager = new ListWalker(); @@ -376,16 +346,7 @@ export default class MessageManager { return { ...msg, ...decoded }; } - private readonly incomingMessages: Message[] = [] - appendMessage(msg: Message, index: number) { - //TODO: put index in message type - this.incomingMessages.push(msg) - if (!this.waitingForFiles) { - this.distributeMessage(msg, index) - } - } - - private distributeMessage(msg: Message, index: number): void { + distributeMessage(msg: Message, index: number): void { const lastMessageTime = Math.max(msg.time, this.lastMessageTime) this.lastMessageTime = lastMessageTime this.state.update({ lastMessageTime }) @@ -529,14 +490,11 @@ export default class MessageManager { private setSize({ height, width }: { height: number, width: number }) { this.screen.scale({ height, width }); this.state.update({ width, height }); - - //this.updateMarketTargets() } // TODO: clean managers? clean() { this.state.update(MessageManager.INITIAL_STATE); - this.incomingMessages.length = 0 } } diff --git a/frontend/app/player/web/WebLivePlayer.ts b/frontend/app/player/web/WebLivePlayer.ts index 6ac2665a1..87e88225a 100644 --- a/frontend/app/player/web/WebLivePlayer.ts +++ b/frontend/app/player/web/WebLivePlayer.ts @@ -1,8 +1,14 @@ import type { Store } from '../common/types' +import type { Message } from './messages' import WebPlayer from './WebPlayer' import AssistManager from './assist/AssistManager' +import MFileReader from './messages/MFileReader' +import { requestEFSDom } from './network/loadFiles' + +import { toast } from 'react-toastify'; // ** + export default class WebLivePlayer extends WebPlayer { static readonly INITIAL_STATE = { @@ -12,21 +18,67 @@ export default class WebLivePlayer extends WebPlayer { } assistManager: AssistManager // public so far - constructor(wpState: Store, session:any, config: RTCIceServer[]) { + private readonly incomingMessages: Message[] = [] + private historyFileIsLoading = false + private lastMessageInFileTime = 0 + private lastMessageInFileIndex = 0 + + constructor(wpState: Store, private session:any, config: RTCIceServer[]) { super(wpState, session, true) - this.assistManager = new AssistManager(session, this.messageManager, this.screen, config, wpState) + this.assistManager = new AssistManager( + session, + f => this.messageManager.setCSSLoading(f), + (msg, idx) => { + this.incomingMessages.push(msg) + if (!this.historyFileIsLoading) { + // TODO: fix index-ing after historyFile-load + this.messageManager.distributeMessage(msg, idx) + } + }, + this.screen, + config, + wpState, + ) this.assistManager.connect(session.agentToken) } - // TODO separate message receivers toggleTimetravel = async () => { - if (!this.wpState.get().liveTimeTravel) { - await this.messageManager.reloadWithUnprocessedFile(() => - this.wpState.update({ - liveTimeTravel: true, - }) - ) + if (this.wpState.get().liveTimeTravel) { + return } + this.historyFileIsLoading = true + this.messageManager.setMessagesLoading(true) // do it in one place. update unique loading states each time instead + this.messageManager.resetMessageManagers() + + try { + const bytes = await requestEFSDom(this.session.sessionId) + const fileReader = new MFileReader(bytes, this.session.startedAt) + for (let msg = fileReader.readNext();msg !== null;msg = fileReader.readNext()) { + this.messageManager.distributeMessage(msg, msg._index) + } + this.wpState.update({ + liveTimeTravel: true, + }) + // here we need to update also lists state, if we gonna use them this.messageManager.onFileReadSuccess + } catch(e) { + toast.error('Error requesting a session file') + console.error("EFS file download error:", e) + } + + // Append previously received messages + this.incomingMessages + .filter(msg => msg.time >= this.lastMessageInFileTime) + .forEach((msg, i) => this.messageManager.distributeMessage(msg, this.lastMessageInFileIndex + i)) + this.incomingMessages.length = 0 + + this.historyFileIsLoading = false + this.messageManager.setMessagesLoading(false) + } + + clean = () => { + this.incomingMessages.length = 0 + this.assistManager.clean() + super.clean() } } \ No newline at end of file diff --git a/frontend/app/player/web/assist/AssistManager.ts b/frontend/app/player/web/assist/AssistManager.ts index 25763ef76..ec41e5382 100644 --- a/frontend/app/player/web/assist/AssistManager.ts +++ b/frontend/app/player/web/assist/AssistManager.ts @@ -1,7 +1,7 @@ import type { Socket } from 'socket.io-client'; -import type MessageManager from '../MessageManager'; import type Screen from '../Screen/Screen'; import type { Store } from '../../common/types' +import type { Message } from '../messages'; import MStreamReader from '../messages/MStreamReader'; import JSONRawMessageReader from '../messages/JSONRawMessageReader' import appStore from 'App/store'; @@ -64,7 +64,8 @@ export default class AssistManager { // TODO: Session type constructor( private session: any, - private md: MessageManager, + private setMessagesLoading: (flag: boolean) => void, + private handleMessage: (m: Message, index: number) => void, private screen: Screen, private config: RTCIceServer[], private store: Store, @@ -88,9 +89,9 @@ export default class AssistManager { } if (status === ConnectionStatus.Connecting) { - this.md.setMessagesLoading(true); + this.setMessagesLoading(true); } else { - this.md.setMessagesLoading(false); + this.setMessagesLoading(false); } if (status === ConnectionStatus.Connected) { this.screen.display(true); @@ -174,8 +175,7 @@ export default class AssistManager { } for (let msg = reader.readNext();msg !== null;msg = reader.readNext()) { - // @ts-ignore TODO: make index a thing. - this.md.appendMessage(msg, msg._index) + this.handleMessage(msg, msg._index) } }) diff --git a/frontend/app/player/web/messages/MStreamReader.ts b/frontend/app/player/web/messages/MStreamReader.ts index a37e43c46..4b08aae9e 100644 --- a/frontend/app/player/web/messages/MStreamReader.ts +++ b/frontend/app/player/web/messages/MStreamReader.ts @@ -12,7 +12,7 @@ export default class MStreamReader { private t: number = 0 private idx: number = 0 - readNext(): Message | null { + readNext(): Message & { _index: number } | null { let msg = this.r.readMessage() if (msg === null) { return null } if (msg.tp === MType.Timestamp) {