openreplay/frontend/app/player/web/messages/MFileReader.ts
Delirium 35461acaf3
[WIP] Mobile replayer (#1452)
* fix(ui): fix up mobile recordings display

* fix(ui): some messages

* fix(ui): some messages

* fix(player): fix msg generation for ios messages

* feat(player): add generic mmanager interface for ios player impl

* feat(player): mobile player and message manager; touch manager; videoplayer

* feat(player): add iphone shells, add log panel,

* feat(player): detect ios sessions and inject correct player

* feat(player): move screen mapper to utils

* feat(player): events panel for mobile, map shell sizes to device type data,

* feat(player): added network tab to mobile player; unify network message (ios and web)

* feat(player): resize canvas up to phone screen size, fix capitalize util

* feat(player): some general changes to support mobile events and network entries

* feat(player): remove swipes from timeline

* feat(player): more stuff for list walker

* fix(ui): performance tab, mobile project typings and form

* fix(ui):some ui touches for ios replayer shell

* fix(ui): more fixes for ui, new onboarding screen for mobile projects

* feat(ui): mobile overview panel (xray)

* feat(ui): fixes for phone shell and tap events

* fix(tracker): change phone shells and sizes

* fix(tracker): fix border on replay screen

* feat(ui): use crashes from db to show in session

* feat(ui): use event name for xray

* feat(ui): some overall ui fixes

* feat(ui): IOS -> iOS

* feat(ui): change tags to ant d

* fix(ui): fast fix

* fix(ui): fix for capitalizer

* fix(ui): fix for browser display

* fix(ui): fix for note popup

* fix(ui): change exceptions display

* fix(ui): add click rage to ios xray

* fix(ui): some icons and resizing

* fix(ui): fix ios context menu overlay, fix console logs creation for ios

* feat(ui): added icons

* feat(ui): performance warnings

* feat(ui): performance warnings

* feat(ui): different styles

* feat(ui): rm debug true

* feat(ui): fix warnings display

* feat(ui): some styles for animation

* feat(ui): add some animations to warnings

* feat(ui): move perf warnings to performance graph

* feat(ui): hide/show warns dynamically

* feat(ui): new mobile touch animation

* fix(tracker): update msg for ios

* fix(ui): taprage fixes

* fix(ui): regenerate icons and messages

* fix(ui): fix msgs

* fix(backend): fix events gen

* fix(backend): fix userid msg
2023-10-27 12:12:09 +02:00

110 lines
3.1 KiB
TypeScript

import type { Message } from './message.gen';
import type { RawMessage } from './raw.gen';
import { MType } from './raw.gen';
import RawMessageReader from './RawMessageReader.gen';
import rewriteMessage from './rewriter/rewriteMessage'
import Logger from 'App/logger'
// TODO: composition instead of inheritance
// needSkipMessage() and next() methods here use buf and p protected properties,
// which should be probably somehow incapsulated
export default class MFileReader extends RawMessageReader {
private pLastMessageID: number = 0
private currentTime: number
public error: boolean = false
private noIndexes: boolean = false
constructor(data: Uint8Array, private startTime?: number, private logger= console) {
super(data)
// if (noIndexes) this.noIndexes = true
}
public checkForIndexes() {
// 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff = no indexes + weird failover (don't ask)
const skipIndexes = this.readCustomIndex(this.buf.slice(0, 8)) === 72057594037927940
|| this.readCustomIndex(this.buf.slice(0, 9)) === 72057594037927940
if (skipIndexes) {
this.noIndexes = true
this.skip(8)
return true
}
return false
}
private needSkipMessage(): boolean {
if (this.p === 0) return false
for (let i = 7; i >= 0; i--) {
if (this.buf[ this.p + i ] !== this.buf[ this.pLastMessageID + i ]) {
return this.buf[ this.p + i ] < this.buf[ this.pLastMessageID + i ]
}
}
return false
}
private getLastMessageID(): number {
let id = 0
for (let i = 0; i< 8; i++) {
id += this.buf[ this.p + i ] * 2**(8*i)
}
return id
}
private readRawMessage(): RawMessage | null {
if (!this.noIndexes) this.skip(8)
try {
const msg = super.readMessage()
if (!msg) {
this.skip(-8)
}
return msg
} catch (e) {
this.error = true
this.logger.error("Read message error:", e)
return null
}
}
currentTab = 'back-compatability'
readNext(): Message & { _index?: number } | null {
if (this.error || !this.hasNextByte()) {
return null
}
while (!this.noIndexes && this.needSkipMessage()) {
const skippedMessage = this.readRawMessage()
if (!skippedMessage) {
return null
}
Logger.group("Openreplay: Skipping messages ", skippedMessage)
}
this.pLastMessageID = this.noIndexes ? 0 : this.p
const rMsg = this.readRawMessage()
if (!rMsg) {
return null
}
if (rMsg.tp === MType.TabData) {
this.currentTab = rMsg.tabId
return this.readNext()
}
if (rMsg.tp === MType.Timestamp) {
if (!this.startTime) {
this.startTime = rMsg.timestamp
}
this.currentTime = rMsg.timestamp - this.startTime
return {
tp: 9999,
time: this.currentTime,
}
}
const index = this.noIndexes ? 0 : this.getLastMessageID()
const msg = Object.assign(rewriteMessage(rMsg), {
time: this.currentTime || rMsg.timestamp - this.startTime!,
tabId: this.currentTab,
}, !this.noIndexes ? { _index: index } : {})
return msg
}
}