ui: fix spritemap generation for assist sessions
This commit is contained in:
parent
421b3d1dc5
commit
e95bdab478
4 changed files with 80 additions and 77 deletions
|
|
@ -43,27 +43,6 @@ export default class MessageLoader {
|
|||
this.session = session;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: has to be moved out of messageLoader logic somehow
|
||||
* */
|
||||
spriteMapSvg: SVGElement | null = null;
|
||||
|
||||
potentialSpriteMap: Record<string, any> = {};
|
||||
|
||||
domParser: DOMParser | null = null;
|
||||
|
||||
createSpriteMap = () => {
|
||||
if (!this.spriteMapSvg) {
|
||||
this.domParser = new DOMParser();
|
||||
this.spriteMapSvg = document.createElementNS(
|
||||
'http://www.w3.org/2000/svg',
|
||||
'svg',
|
||||
);
|
||||
this.spriteMapSvg.setAttribute('style', 'display: none;');
|
||||
this.spriteMapSvg.setAttribute('id', 'reconstructed-sprite');
|
||||
}
|
||||
};
|
||||
|
||||
createNewParser(
|
||||
shouldDecrypt = true,
|
||||
onMessagesDone: (msgs: PlayerMsg[], file?: string) => void,
|
||||
|
|
@ -101,21 +80,6 @@ export default class MessageLoader {
|
|||
let startTimeSet = false;
|
||||
|
||||
msgs.forEach((msg, i) => {
|
||||
if (msg.tp === MType.SetNodeAttribute) {
|
||||
if (msg.value.includes('_$OPENREPLAY_SPRITE$_')) {
|
||||
this.createSpriteMap();
|
||||
if (!this.domParser) {
|
||||
return console.error('DOM parser is not initialized?');
|
||||
}
|
||||
handleSprites(
|
||||
this.potentialSpriteMap,
|
||||
this.domParser,
|
||||
msg,
|
||||
this.spriteMapSvg!,
|
||||
i,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (msg.tp === MType.Redux || msg.tp === MType.ReduxDeprecated) {
|
||||
if ('actionTime' in msg && msg.actionTime) {
|
||||
msg.time = msg.actionTime - this.session.startedAt;
|
||||
|
|
@ -153,7 +117,7 @@ export default class MessageLoader {
|
|||
// .sort((m1, m2) => m1.time - m2.time)
|
||||
.sort(brokenDomSorter)
|
||||
.sort(sortIframes);
|
||||
|
||||
|
||||
if (brokenMessages > 0) {
|
||||
console.warn(
|
||||
'Broken timestamp messages',
|
||||
|
|
@ -333,10 +297,6 @@ export default class MessageLoader {
|
|||
|
||||
await Promise.allSettled([restDomFilesPromise, restDevtoolsFilesPromise]);
|
||||
this.messageManager.onFileReadSuccess();
|
||||
// no sprites for mobile
|
||||
if (this.spriteMapSvg && 'injectSpriteMap' in this.messageManager) {
|
||||
this.messageManager.injectSpriteMap(this.spriteMapSvg);
|
||||
}
|
||||
};
|
||||
|
||||
loadEFSMobs = async () => {
|
||||
|
|
@ -471,40 +431,6 @@ function findBrokenNodes(nodes: any[]) {
|
|||
return result;
|
||||
}
|
||||
|
||||
function handleSprites(
|
||||
potentialSpriteMap: Record<string, any>,
|
||||
parser: DOMParser,
|
||||
msg: Record<string, any>,
|
||||
spriteMapSvg: SVGElement,
|
||||
i: number,
|
||||
) {
|
||||
const [_, svgData] = msg.value.split('_$OPENREPLAY_SPRITE$_');
|
||||
const potentialSprite = potentialSpriteMap[svgData];
|
||||
if (potentialSprite) {
|
||||
msg.value = potentialSprite;
|
||||
} else {
|
||||
const svgDoc = parser.parseFromString(svgData, 'image/svg+xml');
|
||||
const originalSvg = svgDoc.querySelector('svg');
|
||||
if (originalSvg) {
|
||||
const symbol = document.createElementNS(
|
||||
'http://www.w3.org/2000/svg',
|
||||
'symbol',
|
||||
);
|
||||
const symbolId = `symbol-${msg.id || `ind-${i}`}`; // Generate an ID if missing
|
||||
symbol.setAttribute('id', symbolId);
|
||||
symbol.setAttribute(
|
||||
'viewBox',
|
||||
originalSvg.getAttribute('viewBox') || '0 0 24 24',
|
||||
);
|
||||
symbol.innerHTML = originalSvg.innerHTML;
|
||||
|
||||
spriteMapSvg.appendChild(symbol);
|
||||
msg.value = `#${symbolId}`;
|
||||
potentialSpriteMap[svgData] = `#${symbolId}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
window.searchOrphans = (msgs) =>
|
||||
findBrokenNodes(msgs.filter((m) => [8, 9, 10, 70].includes(m.tp)));
|
||||
|
|
|
|||
|
|
@ -201,8 +201,16 @@ export default class MessageManager {
|
|||
}
|
||||
|
||||
Object.values(this.tabs).forEach((tab) => tab.onFileReadSuccess?.());
|
||||
|
||||
this.updateSpriteMap();
|
||||
};
|
||||
|
||||
public updateSpriteMap = () => {
|
||||
if (this.spriteMapSvg) {
|
||||
this.injectSpriteMap(this.spriteMapSvg);
|
||||
}
|
||||
}
|
||||
|
||||
public onFileReadFailed = (...e: any[]) => {
|
||||
logger.error(e);
|
||||
this.state.update({ error: true });
|
||||
|
|
@ -337,9 +345,38 @@ export default class MessageManager {
|
|||
this.state.update({ tabChangeEvents: this.tabChangeEvents });
|
||||
}
|
||||
|
||||
spriteMapSvg: SVGElement | null = null;
|
||||
potentialSpriteMap: Record<string, any> = {};
|
||||
domParser: DOMParser | null = null;
|
||||
createSpriteMap = () => {
|
||||
if (!this.spriteMapSvg) {
|
||||
this.domParser = new DOMParser();
|
||||
this.spriteMapSvg = document.createElementNS(
|
||||
'http://www.w3.org/2000/svg',
|
||||
'svg',
|
||||
);
|
||||
this.spriteMapSvg.setAttribute('style', 'display: none;');
|
||||
this.spriteMapSvg.setAttribute('id', 'reconstructed-sprite');
|
||||
}
|
||||
};
|
||||
|
||||
distributeMessage = (msg: Message & { tabId: string }): void => {
|
||||
// @ts-ignore placeholder msg for timestamps
|
||||
if (msg.tp === 9999) return;
|
||||
if (msg.tp === MType.SetNodeAttribute) {
|
||||
if (msg.value.includes('_$OPENREPLAY_SPRITE$_')) {
|
||||
this.createSpriteMap();
|
||||
if (!this.domParser) {
|
||||
return console.error('DOM parser is not initialized?');
|
||||
}
|
||||
handleSprites(
|
||||
this.potentialSpriteMap,
|
||||
this.domParser,
|
||||
msg,
|
||||
this.spriteMapSvg!,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!this.tabs[msg.tabId]) {
|
||||
this.tabsAmount++;
|
||||
this.state.update({
|
||||
|
|
@ -454,3 +491,36 @@ function mapTabs(tabs: Record<string, TabSessionManager>) {
|
|||
|
||||
return tabMap;
|
||||
}
|
||||
|
||||
function handleSprites(
|
||||
potentialSpriteMap: Record<string, any>,
|
||||
parser: DOMParser,
|
||||
msg: Record<string, any>,
|
||||
spriteMapSvg: SVGElement,
|
||||
) {
|
||||
const [_, svgData] = msg.value.split('_$OPENREPLAY_SPRITE$_');
|
||||
const potentialSprite = potentialSpriteMap[svgData];
|
||||
if (potentialSprite) {
|
||||
msg.value = potentialSprite;
|
||||
} else {
|
||||
const svgDoc = parser.parseFromString(svgData, 'image/svg+xml');
|
||||
const originalSvg = svgDoc.querySelector('svg');
|
||||
if (originalSvg) {
|
||||
const symbol = document.createElementNS(
|
||||
'http://www.w3.org/2000/svg',
|
||||
'symbol',
|
||||
);
|
||||
const symbolId = `symbol-${msg.id || `ind-${msg.time}`}`; // Generate an ID if missing
|
||||
symbol.setAttribute('id', symbolId);
|
||||
symbol.setAttribute(
|
||||
'viewBox',
|
||||
originalSvg.getAttribute('viewBox') || '0 0 24 24',
|
||||
);
|
||||
symbol.innerHTML = originalSvg.innerHTML;
|
||||
|
||||
spriteMapSvg.appendChild(symbol);
|
||||
msg.value = `#${symbolId}`;
|
||||
potentialSpriteMap[svgData] = `#${symbolId}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ export default class WebLivePlayer extends WebPlayer {
|
|||
wpState,
|
||||
(id) => this.messageManager.getNode(id),
|
||||
agentId,
|
||||
this.messageManager.updateSpriteMap,
|
||||
uiErrorHandler,
|
||||
);
|
||||
this.assistManager.connect(session.agentToken!, agentId, projectId);
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@ import type { Socket } from 'socket.io-client';
|
|||
import type { PlayerMsg, Store } from 'App/player';
|
||||
import CanvasReceiver from 'Player/web/assist/CanvasReceiver';
|
||||
import { gunzipSync } from 'fflate';
|
||||
import { Message } from '../messages';
|
||||
import { Message, MType } from '../messages';
|
||||
import type Screen from '../Screen/Screen';
|
||||
import MStreamReader from '../messages/MStreamReader';
|
||||
import JSONRawMessageReader from '../messages/JSONRawMessageReader';
|
||||
import Call, { CallingState } from './Call';
|
||||
import RemoteControl, { RemoteControlStatus } from './RemoteControl';
|
||||
import ScreenRecording, { SessionRecordingStatus } from './ScreenRecording';
|
||||
|
||||
import { debounceCall } from 'App/utils'
|
||||
export { RemoteControlStatus, SessionRecordingStatus, CallingState };
|
||||
|
||||
export enum ConnectionStatus {
|
||||
|
|
@ -82,6 +82,7 @@ export default class AssistManager {
|
|||
private store: Store<typeof AssistManager.INITIAL_STATE>,
|
||||
private getNode: MessageManager['getNode'],
|
||||
public readonly agentId: number,
|
||||
private readonly updateSpriteMap: () => void,
|
||||
public readonly uiErrorHandler?: {
|
||||
error: (msg: string) => void;
|
||||
},
|
||||
|
|
@ -243,6 +244,11 @@ export default class AssistManager {
|
|||
msg !== null;
|
||||
msg = reader.readNext()
|
||||
) {
|
||||
if (msg.tp === MType.SetNodeAttribute) {
|
||||
if (msg.value.includes('_$OPENREPLAY_SPRITE$_')) {
|
||||
debounceCall(this.updateSpriteMap, 250)()
|
||||
}
|
||||
}
|
||||
this.handleMessage(msg, msg._index);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue