change(ui): tracker beta v, improvements for assets loading after click on timeline (player.jump)
This commit is contained in:
parent
6742435bc9
commit
a128060248
8 changed files with 82 additions and 31 deletions
|
|
@ -66,7 +66,7 @@ function WebPlayer(props: any) {
|
|||
|
||||
React.useEffect(() => {
|
||||
if (session.events.length > 0 || session.errors.length > 0) {
|
||||
contextValue.player.updateLists(session)
|
||||
contextValue.player?.updateLists?.(session)
|
||||
}
|
||||
}, [session.events, session.errors])
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ export interface Indexed {
|
|||
}
|
||||
|
||||
export interface Moveable {
|
||||
move(time: number): void
|
||||
move(time: number, isJump?: boolean): void
|
||||
}
|
||||
|
||||
export interface Cleanable {
|
||||
|
|
|
|||
|
|
@ -60,12 +60,12 @@ export default class Animator {
|
|||
window.playerJump = this.jump.bind(this)
|
||||
}
|
||||
|
||||
private setTime(time: number) {
|
||||
private setTime(time: number, isJump?: boolean) {
|
||||
this.store.update({
|
||||
time,
|
||||
completed: false,
|
||||
})
|
||||
this.mm.move(time)
|
||||
this.mm.move(time, isJump)
|
||||
}
|
||||
|
||||
private startAnimation() {
|
||||
|
|
@ -183,11 +183,11 @@ export default class Animator {
|
|||
jump = (time: number) => {
|
||||
if (this.store.get().playing) {
|
||||
cancelAnimationFrame(this.animationFrameRequestId)
|
||||
this.setTime(time)
|
||||
this.setTime(time, true)
|
||||
this.startAnimation()
|
||||
this.store.update({ livePlay: time === this.store.get().endTime })
|
||||
} else {
|
||||
this.setTime(time)
|
||||
this.setTime(time, true)
|
||||
this.store.update({ livePlay: time === this.store.get().endTime })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ export default class MessageManager {
|
|||
sorted.forEach(msg => {
|
||||
if (indx > msg._index) outOfOrderCounter++
|
||||
else indx = msg._index
|
||||
this.distributeMessage(msg, msg._index)
|
||||
this.distributeMessage(msg)
|
||||
})
|
||||
|
||||
if (outOfOrderCounter > 0) console.warn("Unsorted mob file, error count: ", outOfOrderCounter)
|
||||
|
|
@ -287,7 +287,7 @@ export default class MessageManager {
|
|||
this.activityManager = new ActivityManager(this.session.duration.milliseconds);
|
||||
}
|
||||
|
||||
move(t: number, index?: number): void {
|
||||
move(t: number, isJump?: boolean, index?: number): void {
|
||||
const stateToUpdate: Partial<State> = {};
|
||||
/* == REFACTOR_ME == */
|
||||
const lastLoadedLocationMsg = this.loadedLocationManager.moveGetLast(t, index);
|
||||
|
|
@ -337,7 +337,7 @@ export default class MessageManager {
|
|||
if (!!lastResize) {
|
||||
this.setSize(lastResize)
|
||||
}
|
||||
this.pagesManager.moveReady(t).then(() => {
|
||||
this.pagesManager.moveReady(t, isJump).then(() => {
|
||||
|
||||
const lastScroll = this.scrollManager.moveGetLast(t, index);
|
||||
if (!!lastScroll && this.screen.window) {
|
||||
|
|
@ -374,7 +374,7 @@ export default class MessageManager {
|
|||
return { ...msg, ...decoded };
|
||||
}
|
||||
|
||||
distributeMessage(msg: Message, index: number): void {
|
||||
distributeMessage(msg: Message): void {
|
||||
const lastMessageTime = Math.max(msg.time, this.lastMessageTime)
|
||||
this.lastMessageTime = lastMessageTime
|
||||
this.state.update({ lastMessageTime })
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
private styleSheets: Map<number, CSSStyleSheet> = new Map()
|
||||
private ppStyleSheets: Map<number, PostponedStyleSheet> = new Map()
|
||||
private stringDict: Record<number,string> = {}
|
||||
|
||||
private attrsBacktrack: Message[] = []
|
||||
|
||||
private upperBodyId: number = -1;
|
||||
private nodeScrollManagers: Map<number, ListWalker<SetNodeScroll>> = new Map()
|
||||
|
|
@ -143,6 +143,7 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
let { name, value } = msg;
|
||||
const vn = this.vElements.get(msg.id)
|
||||
if (!vn) { logger.error("Node not found", msg); return }
|
||||
|
||||
if (vn.node.tagName === "INPUT" && name === "name") {
|
||||
// Otherwise binds local autocomplete values (maybe should ignore on the tracker level)
|
||||
return
|
||||
|
|
@ -152,9 +153,13 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
// if (value.startsWith(window.env.ASSETS_HOST || window.location.origin + '/assets')) {
|
||||
// value = value.replace("?", "%3F");
|
||||
// }
|
||||
if (!value.startsWith("http")) { return }
|
||||
// blob:... value happened here. https://foss.openreplay.com/3/session/7013553567419137
|
||||
// that resulted in that link being unable to load and having 4sec timeout in the below function.
|
||||
if (!value.startsWith("http")) {
|
||||
return
|
||||
}
|
||||
// blob:... value can happen here for some reason.
|
||||
// which will result in that link being unable to load and having 4sec timeout in the below function.
|
||||
|
||||
// TODO: check if node actually exists on the page, not just in memory
|
||||
this.stylesManager.setStyleHandlers(vn.node as HTMLLinkElement, value);
|
||||
}
|
||||
if (vn.node.namespaceURI === 'http://www.w3.org/2000/svg' && value.startsWith("url(")) {
|
||||
|
|
@ -164,8 +169,7 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
this.removeBodyScroll(msg.id, vn)
|
||||
}
|
||||
|
||||
private applyMessage = (msg: Message): Promise<any> | undefined => {
|
||||
let node: Node | undefined
|
||||
private applyMessage = (msg: Message, isJump?: boolean): Promise<any> | undefined => {
|
||||
let vn: VNode | undefined
|
||||
let doc: Document | null
|
||||
let styleSheet: CSSStyleSheet | PostponedStyleSheet | undefined
|
||||
|
|
@ -229,9 +233,12 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
if (!vn) { logger.error("Node not found", msg); return }
|
||||
if (!vn.parentNode) { logger.error("Parent node not found", msg); return }
|
||||
vn.parentNode.removeChild(vn)
|
||||
this.vElements.delete(msg.id)
|
||||
this.vTexts.delete(msg.id)
|
||||
return
|
||||
case MType.SetNodeAttribute:
|
||||
this.setNodeAttribute(msg)
|
||||
if (isJump && msg.name === 'href') this.attrsBacktrack.push(msg)
|
||||
else this.setNodeAttribute(msg)
|
||||
return
|
||||
case MType.StringDict:
|
||||
this.stringDict[msg.key] = msg.value
|
||||
|
|
@ -240,11 +247,14 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
this.stringDict[msg.nameKey] === undefined && logger.error("No dictionary key for msg 'name': ", msg)
|
||||
this.stringDict[msg.valueKey] === undefined && logger.error("No dictionary key for msg 'value': ", msg)
|
||||
if (this.stringDict[msg.nameKey] === undefined || this.stringDict[msg.valueKey] === undefined ) { return }
|
||||
this.setNodeAttribute({
|
||||
id: msg.id,
|
||||
name: this.stringDict[msg.nameKey],
|
||||
value: this.stringDict[msg.valueKey],
|
||||
})
|
||||
if (isJump && this.stringDict[msg.nameKey] === 'href') this.attrsBacktrack.push(msg)
|
||||
else {
|
||||
this.setNodeAttribute({
|
||||
id: msg.id,
|
||||
name: this.stringDict[msg.nameKey],
|
||||
value: this.stringDict[msg.valueKey],
|
||||
})
|
||||
}
|
||||
return
|
||||
case MType.RemoveNodeAttribute:
|
||||
vn = this.vElements.get(msg.id)
|
||||
|
|
@ -422,13 +432,53 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
}
|
||||
}
|
||||
|
||||
async moveReady(t: number): Promise<void> {
|
||||
applyBacktrack(msg: Message) {
|
||||
// @ts-ignore
|
||||
const target = this.vElements.get(msg.id)
|
||||
if (!target) {
|
||||
return
|
||||
}
|
||||
|
||||
switch (msg.tp) {
|
||||
case MType.SetNodeAttribute: {
|
||||
this.setNodeAttribute(msg)
|
||||
return
|
||||
}
|
||||
case MType.SetNodeAttributeDict: {
|
||||
this.stringDict[msg.nameKey] === undefined && logger.error("No dictionary key for msg 'name': ", msg)
|
||||
this.stringDict[msg.valueKey] === undefined && logger.error("No dictionary key for msg 'value': ", msg)
|
||||
if (this.stringDict[msg.nameKey] === undefined || this.stringDict[msg.valueKey] === undefined) {
|
||||
return
|
||||
}
|
||||
this.setNodeAttribute({
|
||||
id: msg.id,
|
||||
name: this.stringDict[msg.nameKey],
|
||||
value: this.stringDict[msg.valueKey],
|
||||
})
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async moveReady(t: number, isJump?: boolean): Promise<void> {
|
||||
// MBTODO (back jump optimisation):
|
||||
// - store intemediate virtual dom state
|
||||
// - cancel previous moveReady tasks (is it possible?) if new timestamp is less
|
||||
// This function autoresets pointer if necessary (better name?)
|
||||
|
||||
await this.moveWait(t, this.applyMessage)
|
||||
|
||||
/**
|
||||
* Basically just skipping all set attribute with attrs being "href" if user is 'jumping'
|
||||
* to the other point of replay to save time on NOT downloading any resources before the dom tree changes
|
||||
* are applied, so it won't try to download and then cancel when node is created in msg N and removed in msg N+2
|
||||
* which produces weird bug when asset is cached (10-25ms delay)
|
||||
* */
|
||||
await this.moveWait(t, (msg) => this.applyMessage(msg, isJump))
|
||||
if (isJump) {
|
||||
this.attrsBacktrack.forEach(msg => {
|
||||
this.applyBacktrack(msg)
|
||||
})
|
||||
this.attrsBacktrack = []
|
||||
}
|
||||
this.vRoots.forEach(rt => rt.applyChanges()) // MBTODO (optimisation): affected set
|
||||
|
||||
// Thinkabout (read): css preload
|
||||
|
|
|
|||
|
|
@ -108,8 +108,8 @@ export class VElement extends VParent {
|
|||
} else {
|
||||
try {
|
||||
this.node.setAttribute(key, value)
|
||||
} catch {
|
||||
// log err
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -134,7 +134,8 @@ export class VStyleElement extends VElement {
|
|||
this.stylesheetCallbacks.forEach(cb => cb(sheet))
|
||||
this.stylesheetCallbacks = []
|
||||
} else {
|
||||
console.warn("Style onload: sheet is null")
|
||||
// console.warn("Style onload: sheet is null") ?
|
||||
// sometimes logs shit ton of errors for some reason
|
||||
}
|
||||
this.loaded = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,14 +33,14 @@ export default class PagesManager extends ListWalker<DOMManager> {
|
|||
this.forEach(page => page.sort(comparator))
|
||||
}
|
||||
|
||||
moveReady(t: number): Promise<void> {
|
||||
moveReady(t: number, isJump?: boolean): Promise<void> {
|
||||
const requiredPage = this.moveGetLast(t)
|
||||
if (requiredPage != null) {
|
||||
this.currentPage = requiredPage
|
||||
this.currentPage.reset() // Otherwise it won't apply create_document
|
||||
}
|
||||
if (this.currentPage != null) {
|
||||
return this.currentPage.moveReady(t)
|
||||
return this.currentPage.moveReady(t, isJump)
|
||||
}
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@openreplay/tracker",
|
||||
"description": "The OpenReplay tracker main package",
|
||||
"version": "5.0.1",
|
||||
"version": "5.0.2-beta.2",
|
||||
"keywords": [
|
||||
"logging",
|
||||
"replay"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue