Merge 345d099d8c into 13e83fa774
This commit is contained in:
commit
e0c455be74
24 changed files with 2357 additions and 1983 deletions
|
|
@ -10,5 +10,5 @@ func IsMobileType(id int) bool {
|
|||
}
|
||||
|
||||
func IsDOMType(id int) bool {
|
||||
return 0 == id || 4 == id || 5 == id || 6 == id || 7 == id || 8 == id || 9 == id || 10 == id || 11 == id || 12 == id || 13 == id || 14 == id || 15 == id || 16 == id || 18 == id || 19 == id || 20 == id || 34 == id || 35 == id || 37 == id || 38 == id || 49 == id || 50 == id || 51 == id || 43 == id || 52 == id || 54 == id || 55 == id || 57 == id || 58 == id || 59 == id || 60 == id || 61 == id || 67 == id || 68 == id || 69 == id || 70 == id || 71 == id || 72 == id || 73 == id || 74 == id || 75 == id || 76 == id || 77 == id || 113 == id || 114 == id || 117 == id || 118 == id || 119 == id || 122 == id || 93 == id || 96 == id || 100 == id || 101 == id || 102 == id || 103 == id || 104 == id || 105 == id || 106 == id || 111 == id
|
||||
return 0 == id || 4 == id || 5 == id || 6 == id || 7 == id || 8 == id || 9 == id || 10 == id || 11 == id || 12 == id || 13 == id || 14 == id || 15 == id || 16 == id || 18 == id || 19 == id || 20 == id || 34 == id || 35 == id || 36 == id || 37 == id || 38 == id || 49 == id || 50 == id || 51 == id || 43 == id || 52 == id || 54 == id || 55 == id || 57 == id || 58 == id || 59 == id || 60 == id || 61 == id || 65 == id || 67 == id || 68 == id || 69 == id || 70 == id || 71 == id || 72 == id || 73 == id || 74 == id || 75 == id || 76 == id || 77 == id || 113 == id || 114 == id || 117 == id || 118 == id || 119 == id || 122 == id || 93 == id || 96 == id || 100 == id || 101 == id || 102 == id || 103 == id || 104 == id || 105 == id || 106 == id || 111 == id
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -356,6 +356,14 @@ class SetNodeAttributeDictGlobal(Message):
|
|||
self.value = value
|
||||
|
||||
|
||||
class NodeAnimationResult(Message):
|
||||
__id__ = 36
|
||||
|
||||
def __init__(self, id, styles):
|
||||
self.id = id
|
||||
self.styles = styles
|
||||
|
||||
|
||||
class CSSInsertRule(Message):
|
||||
__id__ = 37
|
||||
|
||||
|
|
@ -626,6 +634,14 @@ class CustomIssue(Message):
|
|||
self.payload = payload
|
||||
|
||||
|
||||
class SetNodeSlot(Message):
|
||||
__id__ = 65
|
||||
|
||||
def __init__(self, id, slot_id):
|
||||
self.id = id
|
||||
self.slot_id = slot_id
|
||||
|
||||
|
||||
class AssetCache(Message):
|
||||
__id__ = 66
|
||||
|
||||
|
|
|
|||
|
|
@ -535,6 +535,17 @@ cdef class SetNodeAttributeDictGlobal(PyMessage):
|
|||
self.value = value
|
||||
|
||||
|
||||
cdef class NodeAnimationResult(PyMessage):
|
||||
cdef public int __id__
|
||||
cdef public unsigned long id
|
||||
cdef public str styles
|
||||
|
||||
def __init__(self, unsigned long id, str styles):
|
||||
self.__id__ = 36
|
||||
self.id = id
|
||||
self.styles = styles
|
||||
|
||||
|
||||
cdef class CSSInsertRule(PyMessage):
|
||||
cdef public int __id__
|
||||
cdef public unsigned long id
|
||||
|
|
@ -935,6 +946,17 @@ cdef class CustomIssue(PyMessage):
|
|||
self.payload = payload
|
||||
|
||||
|
||||
cdef class SetNodeSlot(PyMessage):
|
||||
cdef public int __id__
|
||||
cdef public unsigned long id
|
||||
cdef public unsigned long slot_id
|
||||
|
||||
def __init__(self, unsigned long id, unsigned long slot_id):
|
||||
self.__id__ = 65
|
||||
self.id = id
|
||||
self.slot_id = slot_id
|
||||
|
||||
|
||||
cdef class AssetCache(PyMessage):
|
||||
cdef public int __id__
|
||||
cdef public str url
|
||||
|
|
|
|||
|
|
@ -373,6 +373,12 @@ class MessageCodec(Codec):
|
|||
value=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 36:
|
||||
return NodeAnimationResult(
|
||||
id=self.read_uint(reader),
|
||||
styles=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 37:
|
||||
return CSSInsertRule(
|
||||
id=self.read_uint(reader),
|
||||
|
|
@ -587,6 +593,12 @@ class MessageCodec(Codec):
|
|||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 65:
|
||||
return SetNodeSlot(
|
||||
id=self.read_uint(reader),
|
||||
slot_id=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 66:
|
||||
return AssetCache(
|
||||
url=self.read_string(reader)
|
||||
|
|
|
|||
|
|
@ -471,6 +471,12 @@ cdef class MessageCodec:
|
|||
value=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 36:
|
||||
return NodeAnimationResult(
|
||||
id=self.read_uint(reader),
|
||||
styles=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 37:
|
||||
return CSSInsertRule(
|
||||
id=self.read_uint(reader),
|
||||
|
|
@ -685,6 +691,12 @@ cdef class MessageCodec:
|
|||
payload=self.read_string(reader)
|
||||
)
|
||||
|
||||
if message_id == 65:
|
||||
return SetNodeSlot(
|
||||
id=self.read_uint(reader),
|
||||
slot_id=self.read_uint(reader)
|
||||
)
|
||||
|
||||
if message_id == 66:
|
||||
return AssetCache(
|
||||
url=self.read_string(reader)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import FocusManager from './FocusManager';
|
|||
import SelectionManager from './SelectionManager';
|
||||
import {
|
||||
StyleElement,
|
||||
VSpriteMap,
|
||||
OnloadStyleSheet,
|
||||
VDocument,
|
||||
VElement,
|
||||
|
|
@ -17,6 +16,7 @@ import {
|
|||
VShadowRoot,
|
||||
VText,
|
||||
OnloadVRoot,
|
||||
VSlot,
|
||||
} from './VirtualDOM';
|
||||
import { deleteRule, insertRule } from './safeCSSRules';
|
||||
|
||||
|
|
@ -54,7 +54,6 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
*/
|
||||
private olStyleSheets: Map<number, OnloadStyleSheet> = new Map();
|
||||
/** @depreacted since tracker 4.0.2 Mapping by nodeID */
|
||||
private olStyleSheetsDeprecated: Map<number, OnloadStyleSheet> = new Map();
|
||||
private upperBodyId: number = -1;
|
||||
private nodeScrollManagers: Map<number, ListWalker<SetNodeScroll>> =
|
||||
new Map();
|
||||
|
|
@ -70,7 +69,7 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
};
|
||||
public readonly time: number;
|
||||
private virtualMode = false;
|
||||
private hasSlots = false
|
||||
private hasSlots = false;
|
||||
private showVModeBadge?: () => void;
|
||||
|
||||
constructor(params: {
|
||||
|
|
@ -278,6 +277,36 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
this.stylesManager.reset();
|
||||
return;
|
||||
}
|
||||
case MType.SetNodeSlot: {
|
||||
const vChild = this.vElements.get(msg.id) || this.vTexts.get(msg.id);
|
||||
if (!vChild) {
|
||||
logger.error('SetNodeSlot: Node not found', msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.slotID > 0) {
|
||||
const slotElem = this.vElements.get(msg.slotID);
|
||||
if (!(slotElem instanceof VSlot)) {
|
||||
logger.error('SetNodeSlot: Slot not found', msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vChild instanceof VElement) {
|
||||
const slotName = (slotElem.node as HTMLSlotElement).name;
|
||||
if (slotName && slotName !== 'default') {
|
||||
vChild.setAttribute('slot', slotName);
|
||||
} else {
|
||||
// if el goes to default slot, we don't need attr
|
||||
vChild.removeAttribute('slot');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (vChild instanceof VElement) {
|
||||
vChild.removeAttribute('slot');
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
case MType.CreateTextNode: {
|
||||
const vText = new VText();
|
||||
this.vTexts.set(msg.id, vText);
|
||||
|
|
@ -286,7 +315,10 @@ export default class DOMManager extends ListWalker<Message> {
|
|||
}
|
||||
case MType.CreateElementNode: {
|
||||
// if (msg.tag.toLowerCase() === 'canvas') msg.tag = 'video'
|
||||
const vElem = new VElement(msg.tag, msg.svg, msg.index, msg.id);
|
||||
const vElem =
|
||||
msg.tag === 'SLOT'
|
||||
? new VSlot(msg.tag, msg.svg, msg.index, msg.id)
|
||||
: new VElement(msg.tag, msg.svg, msg.index, msg.id);
|
||||
if (['STYLE', 'style', 'LINK'].includes(msg.tag)) {
|
||||
vElem.prioritized = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ type Callback<T> = (o: T) => void;
|
|||
*/
|
||||
export abstract class VNode<T extends Node = Node> {
|
||||
protected abstract createNode(): T;
|
||||
|
||||
assignedSlot: VSlot | null = null;
|
||||
private _node: T | null;
|
||||
|
||||
/**
|
||||
|
|
@ -58,13 +58,13 @@ export abstract class VNode<T extends Node = Node> {
|
|||
public abstract applyChanges(): void;
|
||||
}
|
||||
|
||||
type VChild = VElement | VText | VSpriteMap;
|
||||
type VChild = VElement | VText;
|
||||
abstract class VParent<T extends Node = Node> extends VNode<T> {
|
||||
/**
|
||||
*/
|
||||
protected children: VChild[] = [];
|
||||
|
||||
private notMontedChildren: Set<VChild> = new Set();
|
||||
protected notMontedChildren: Set<VChild> = new Set();
|
||||
|
||||
insertChildAt(child: VChild, index: number) {
|
||||
if (child.parentNode) {
|
||||
|
|
@ -85,6 +85,9 @@ abstract class VParent<T extends Node = Node> extends VNode<T> {
|
|||
let nextMounted: VChild | null = null;
|
||||
for (let i = this.children.length - 1; i >= 0; i--) {
|
||||
const child = this.children[i];
|
||||
if (child.assignedSlot) {
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
this.notMontedChildren.has(child) &&
|
||||
(!shouldInsert || shouldInsert(child)) // is there a better way of not-knowing about subclass logic on prioritized insertion?
|
||||
|
|
@ -107,14 +110,15 @@ abstract class VParent<T extends Node = Node> extends VNode<T> {
|
|||
/* Inserting */
|
||||
this.mountChildren();
|
||||
if (this.notMontedChildren.size !== 0) {
|
||||
console.error('VParent: Something went wrong with children insertion');
|
||||
console.error('VParent: Something went wrong with children insertion', this.notMontedChildren);
|
||||
}
|
||||
/* Removing in-between */
|
||||
const { node } = this;
|
||||
const realChildren = node.childNodes;
|
||||
if (realChildren.length > 0 && this.children.length > 0) {
|
||||
for (let j = 0; j < this.children.length; j++) {
|
||||
while (realChildren[j] !== this.children[j].node) {
|
||||
const expected = this.children.filter((c) => !c.assignedSlot);
|
||||
if (realChildren.length > 0 && expected.length > 0) {
|
||||
for (let j = 0; j < expected.length; j++) {
|
||||
while (realChildren[j] !== expected[j].node) {
|
||||
if (isNode(realChildren[j])) {
|
||||
node.removeChild(realChildren[j]);
|
||||
}
|
||||
|
|
@ -122,7 +126,7 @@ abstract class VParent<T extends Node = Node> extends VNode<T> {
|
|||
}
|
||||
}
|
||||
/* Removing tail */
|
||||
while (realChildren.length > this.children.length) {
|
||||
while (realChildren.length > expected.length) {
|
||||
node.removeChild(
|
||||
node.lastChild as Node,
|
||||
); /* realChildren.length > this.children.length >= 0 so it is not null */
|
||||
|
|
@ -159,46 +163,6 @@ export class VShadowRoot extends VParent<ShadowRoot> {
|
|||
|
||||
export type VRoot = VDocument | VShadowRoot;
|
||||
|
||||
export class VSpriteMap extends VParent<Element> {
|
||||
parentNode: VParent | null =
|
||||
null; /** Should be modified only by he parent itself */
|
||||
|
||||
private newAttributes: Map<string, string | false> = new Map();
|
||||
|
||||
constructor(
|
||||
readonly tagName: string,
|
||||
readonly isSVG = true,
|
||||
public readonly index: number,
|
||||
private readonly nodeId: number,
|
||||
) {
|
||||
super();
|
||||
this.createNode();
|
||||
}
|
||||
|
||||
protected createNode() {
|
||||
try {
|
||||
const element = document.createElementNS(
|
||||
'http://www.w3.org/2000/svg',
|
||||
this.tagName,
|
||||
);
|
||||
element.dataset.openreplayId = this.nodeId.toString();
|
||||
return element;
|
||||
} catch (e) {
|
||||
console.error(
|
||||
'Openreplay: Player received invalid html tag',
|
||||
this.tagName,
|
||||
e,
|
||||
);
|
||||
return document.createElement(this.tagName.replace(/[^a-z]/gi, ''));
|
||||
}
|
||||
}
|
||||
|
||||
applyChanges() {
|
||||
// this is a hack to prevent the sprite map from being removed from the DOM
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export class VElement extends VParent<Element> {
|
||||
parentNode: VParent | null =
|
||||
null; /** Should be modified only by he parent itself */
|
||||
|
|
@ -293,6 +257,18 @@ export class VElement extends VParent<Element> {
|
|||
}
|
||||
}
|
||||
|
||||
export class VSlot extends VElement {
|
||||
protected createNode() {
|
||||
const element = super.createNode() as HTMLSlotElement;
|
||||
return element;
|
||||
}
|
||||
|
||||
applyChanges() {
|
||||
super.applyChanges();
|
||||
// todo safety checks here ?
|
||||
}
|
||||
}
|
||||
|
||||
export class VHTMLElement extends VElement {
|
||||
constructor(node: HTMLElement) {
|
||||
super('HTML', false);
|
||||
|
|
|
|||
|
|
@ -255,6 +255,16 @@ export default class RawMessageReader extends PrimitiveReader {
|
|||
};
|
||||
}
|
||||
|
||||
case 36: {
|
||||
const id = this.readUint(); if (id === null) { return resetPointer() }
|
||||
const styles = this.readString(); if (styles === null) { return resetPointer() }
|
||||
return {
|
||||
tp: MType.NodeAnimationResult,
|
||||
id,
|
||||
styles,
|
||||
};
|
||||
}
|
||||
|
||||
case 37: {
|
||||
const id = this.readUint(); if (id === null) { return resetPointer() }
|
||||
const rule = this.readString(); if (rule === null) { return resetPointer() }
|
||||
|
|
@ -547,6 +557,16 @@ export default class RawMessageReader extends PrimitiveReader {
|
|||
};
|
||||
}
|
||||
|
||||
case 65: {
|
||||
const id = this.readUint(); if (id === null) { return resetPointer() }
|
||||
const slotID = this.readUint(); if (slotID === null) { return resetPointer() }
|
||||
return {
|
||||
tp: MType.SetNodeSlot,
|
||||
id,
|
||||
slotID,
|
||||
};
|
||||
}
|
||||
|
||||
case 67: {
|
||||
const id = this.readUint(); if (id === null) { return resetPointer() }
|
||||
const rule = this.readString(); if (rule === null) { return resetPointer() }
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
import { MType } from './raw.gen'
|
||||
|
||||
const IOS_TYPES = [90,91,92,93,94,95,96,97,98,100,101,102,103,104,105,106,107,110,111]
|
||||
const DOM_TYPES = [0,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,34,35,37,38,49,50,51,43,52,54,55,57,58,59,60,61,67,68,69,70,71,72,73,74,75,76,77,113,114,117,118,119,122]
|
||||
const DOM_TYPES = [0,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,34,35,36,37,38,49,50,51,43,52,54,55,57,58,59,60,61,65,67,68,69,70,71,72,73,74,75,76,77,113,114,117,118,119,122]
|
||||
export function isDOMType(t: MType) {
|
||||
return DOM_TYPES.includes(t)
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@ import type {
|
|||
RawConsoleLog,
|
||||
RawStringDictGlobal,
|
||||
RawSetNodeAttributeDictGlobal,
|
||||
RawNodeAnimationResult,
|
||||
RawCssInsertRule,
|
||||
RawCssDeleteRule,
|
||||
RawFetch,
|
||||
|
|
@ -48,6 +49,7 @@ import type {
|
|||
RawLongTask,
|
||||
RawSetNodeAttributeURLBased,
|
||||
RawSetCssDataURLBased,
|
||||
RawSetNodeSlot,
|
||||
RawCssInsertRuleURLBased,
|
||||
RawMouseClick,
|
||||
RawMouseClickDeprecated,
|
||||
|
|
@ -132,6 +134,8 @@ export type StringDictGlobal = RawStringDictGlobal & Timed
|
|||
|
||||
export type SetNodeAttributeDictGlobal = RawSetNodeAttributeDictGlobal & Timed
|
||||
|
||||
export type NodeAnimationResult = RawNodeAnimationResult & Timed
|
||||
|
||||
export type CssInsertRule = RawCssInsertRule & Timed
|
||||
|
||||
export type CssDeleteRule = RawCssDeleteRule & Timed
|
||||
|
|
@ -178,6 +182,8 @@ export type SetNodeAttributeURLBased = RawSetNodeAttributeURLBased & Timed
|
|||
|
||||
export type SetCssDataURLBased = RawSetCssDataURLBased & Timed
|
||||
|
||||
export type SetNodeSlot = RawSetNodeSlot & Timed
|
||||
|
||||
export type CssInsertRuleURLBased = RawCssInsertRuleURLBased & Timed
|
||||
|
||||
export type MouseClick = RawMouseClick & Timed
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ export const enum MType {
|
|||
ConsoleLog = 22,
|
||||
StringDictGlobal = 34,
|
||||
SetNodeAttributeDictGlobal = 35,
|
||||
NodeAnimationResult = 36,
|
||||
CssInsertRule = 37,
|
||||
CssDeleteRule = 38,
|
||||
Fetch = 39,
|
||||
|
|
@ -46,6 +47,7 @@ export const enum MType {
|
|||
LongTask = 59,
|
||||
SetNodeAttributeURLBased = 60,
|
||||
SetCssDataURLBased = 61,
|
||||
SetNodeSlot = 65,
|
||||
CssInsertRuleURLBased = 67,
|
||||
MouseClick = 68,
|
||||
MouseClickDeprecated = 69,
|
||||
|
|
@ -225,6 +227,12 @@ export interface RawSetNodeAttributeDictGlobal {
|
|||
value: number,
|
||||
}
|
||||
|
||||
export interface RawNodeAnimationResult {
|
||||
tp: MType.NodeAnimationResult,
|
||||
id: number,
|
||||
styles: string,
|
||||
}
|
||||
|
||||
export interface RawCssInsertRule {
|
||||
tp: MType.CssInsertRule,
|
||||
id: number,
|
||||
|
|
@ -394,6 +402,12 @@ export interface RawSetCssDataURLBased {
|
|||
baseURL: string,
|
||||
}
|
||||
|
||||
export interface RawSetNodeSlot {
|
||||
tp: MType.SetNodeSlot,
|
||||
id: number,
|
||||
slotID: number,
|
||||
}
|
||||
|
||||
export interface RawCssInsertRuleURLBased {
|
||||
tp: MType.CssInsertRuleURLBased,
|
||||
id: number,
|
||||
|
|
@ -703,4 +717,4 @@ export interface RawMobileIssueEvent {
|
|||
}
|
||||
|
||||
|
||||
export type RawMessage = RawTimestamp | RawSetPageLocationDeprecated | RawSetViewportSize | RawSetViewportScroll | RawCreateDocument | RawCreateElementNode | RawCreateTextNode | RawMoveNode | RawRemoveNode | RawSetNodeAttribute | RawRemoveNodeAttribute | RawSetNodeData | RawSetCssData | RawSetNodeScroll | RawSetInputValue | RawSetInputChecked | RawMouseMove | RawNetworkRequestDeprecated | RawConsoleLog | RawStringDictGlobal | RawSetNodeAttributeDictGlobal | RawCssInsertRule | RawCssDeleteRule | RawFetch | RawProfiler | RawOTable | RawReduxDeprecated | RawVuex | RawMobX | RawNgRx | RawGraphQlDeprecated | RawPerformanceTrack | RawStringDictDeprecated | RawSetNodeAttributeDictDeprecated | RawStringDict | RawSetNodeAttributeDict | RawResourceTimingDeprecatedDeprecated | RawConnectionInformation | RawSetPageVisibility | RawLoadFontFace | RawSetNodeFocus | RawLongTask | RawSetNodeAttributeURLBased | RawSetCssDataURLBased | RawCssInsertRuleURLBased | RawMouseClick | RawMouseClickDeprecated | RawCreateIFrameDocument | RawAdoptedSsReplaceURLBased | RawAdoptedSsReplace | RawAdoptedSsInsertRuleURLBased | RawAdoptedSsInsertRule | RawAdoptedSsDeleteRule | RawAdoptedSsAddOwner | RawAdoptedSsRemoveOwner | RawZustand | RawNetworkRequest | RawWsChannel | RawResourceTiming | RawIncident | RawLongAnimationTask | RawSelectionChange | RawMouseThrashing | RawResourceTimingDeprecated | RawTabChange | RawTabData | RawCanvasNode | RawTagTrigger | RawRedux | RawSetPageLocation | RawGraphQl | RawMobileEvent | RawMobileScreenChanges | RawMobileClickEvent | RawMobileInputEvent | RawMobilePerformanceEvent | RawMobileLog | RawMobileInternalError | RawMobileNetworkCall | RawMobileSwipeEvent | RawMobileIssueEvent;
|
||||
export type RawMessage = RawTimestamp | RawSetPageLocationDeprecated | RawSetViewportSize | RawSetViewportScroll | RawCreateDocument | RawCreateElementNode | RawCreateTextNode | RawMoveNode | RawRemoveNode | RawSetNodeAttribute | RawRemoveNodeAttribute | RawSetNodeData | RawSetCssData | RawSetNodeScroll | RawSetInputValue | RawSetInputChecked | RawMouseMove | RawNetworkRequestDeprecated | RawConsoleLog | RawStringDictGlobal | RawSetNodeAttributeDictGlobal | RawNodeAnimationResult | RawCssInsertRule | RawCssDeleteRule | RawFetch | RawProfiler | RawOTable | RawReduxDeprecated | RawVuex | RawMobX | RawNgRx | RawGraphQlDeprecated | RawPerformanceTrack | RawStringDictDeprecated | RawSetNodeAttributeDictDeprecated | RawStringDict | RawSetNodeAttributeDict | RawResourceTimingDeprecatedDeprecated | RawConnectionInformation | RawSetPageVisibility | RawLoadFontFace | RawSetNodeFocus | RawLongTask | RawSetNodeAttributeURLBased | RawSetCssDataURLBased | RawSetNodeSlot | RawCssInsertRuleURLBased | RawMouseClick | RawMouseClickDeprecated | RawCreateIFrameDocument | RawAdoptedSsReplaceURLBased | RawAdoptedSsReplace | RawAdoptedSsInsertRuleURLBased | RawAdoptedSsInsertRule | RawAdoptedSsDeleteRule | RawAdoptedSsAddOwner | RawAdoptedSsRemoveOwner | RawZustand | RawNetworkRequest | RawWsChannel | RawResourceTiming | RawIncident | RawLongAnimationTask | RawSelectionChange | RawMouseThrashing | RawResourceTimingDeprecated | RawTabChange | RawTabData | RawCanvasNode | RawTagTrigger | RawRedux | RawSetPageLocation | RawGraphQl | RawMobileEvent | RawMobileScreenChanges | RawMobileClickEvent | RawMobileInputEvent | RawMobilePerformanceEvent | RawMobileLog | RawMobileInternalError | RawMobileNetworkCall | RawMobileSwipeEvent | RawMobileIssueEvent;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ export const TP_MAP = {
|
|||
22: MType.ConsoleLog,
|
||||
34: MType.StringDictGlobal,
|
||||
35: MType.SetNodeAttributeDictGlobal,
|
||||
36: MType.NodeAnimationResult,
|
||||
37: MType.CssInsertRule,
|
||||
38: MType.CssDeleteRule,
|
||||
39: MType.Fetch,
|
||||
|
|
@ -47,6 +48,7 @@ export const TP_MAP = {
|
|||
59: MType.LongTask,
|
||||
60: MType.SetNodeAttributeURLBased,
|
||||
61: MType.SetCssDataURLBased,
|
||||
65: MType.SetNodeSlot,
|
||||
67: MType.CssInsertRuleURLBased,
|
||||
68: MType.MouseClick,
|
||||
69: MType.MouseClickDeprecated,
|
||||
|
|
|
|||
|
|
@ -186,6 +186,12 @@ type TrSetNodeAttributeDictGlobal = [
|
|||
value: number,
|
||||
]
|
||||
|
||||
type TrNodeAnimationResult = [
|
||||
type: 36,
|
||||
id: number,
|
||||
styles: string,
|
||||
]
|
||||
|
||||
type TrCSSInsertRule = [
|
||||
type: 37,
|
||||
id: number,
|
||||
|
|
@ -372,6 +378,12 @@ type TrCustomIssue = [
|
|||
payload: string,
|
||||
]
|
||||
|
||||
type TrSetNodeSlot = [
|
||||
type: 65,
|
||||
id: number,
|
||||
slotID: number,
|
||||
]
|
||||
|
||||
type TrCSSInsertRuleURLBased = [
|
||||
type: 67,
|
||||
id: number,
|
||||
|
|
@ -621,7 +633,7 @@ type TrWebVitals = [
|
|||
]
|
||||
|
||||
|
||||
export type TrackerMessage = TrTimestamp | TrSetPageLocationDeprecated | TrSetViewportSize | TrSetViewportScroll | TrCreateDocument | TrCreateElementNode | TrCreateTextNode | TrMoveNode | TrRemoveNode | TrSetNodeAttribute | TrRemoveNodeAttribute | TrSetNodeData | TrSetNodeScroll | TrSetInputTarget | TrSetInputValue | TrSetInputChecked | TrMouseMove | TrNetworkRequestDeprecated | TrConsoleLog | TrPageLoadTiming | TrPageRenderTiming | TrCustomEvent | TrUserID | TrUserAnonymousID | TrMetadata | TrStringDictGlobal | TrSetNodeAttributeDictGlobal | TrCSSInsertRule | TrCSSDeleteRule | TrFetch | TrProfiler | TrOTable | TrStateAction | TrReduxDeprecated | TrVuex | TrMobX | TrNgRx | TrGraphQLDeprecated | TrPerformanceTrack | TrStringDictDeprecated | TrSetNodeAttributeDictDeprecated | TrStringDict | TrSetNodeAttributeDict | TrResourceTimingDeprecatedDeprecated | TrConnectionInformation | TrSetPageVisibility | TrLoadFontFace | TrSetNodeFocus | TrLongTask | TrSetNodeAttributeURLBased | TrSetCSSDataURLBased | TrTechnicalInfo | TrCustomIssue | TrCSSInsertRuleURLBased | TrMouseClick | TrMouseClickDeprecated | TrCreateIFrameDocument | TrAdoptedSSReplaceURLBased | TrAdoptedSSInsertRuleURLBased | TrAdoptedSSDeleteRule | TrAdoptedSSAddOwner | TrAdoptedSSRemoveOwner | TrJSException | TrZustand | TrBatchMetadata | TrPartitionedMessage | TrNetworkRequest | TrWSChannel | TrResourceTiming | TrIncident | TrLongAnimationTask | TrInputChange | TrSelectionChange | TrMouseThrashing | TrUnbindNodes | TrResourceTimingDeprecated | TrTabChange | TrTabData | TrCanvasNode | TrTagTrigger | TrRedux | TrSetPageLocation | TrGraphQL | TrWebVitals
|
||||
export type TrackerMessage = TrTimestamp | TrSetPageLocationDeprecated | TrSetViewportSize | TrSetViewportScroll | TrCreateDocument | TrCreateElementNode | TrCreateTextNode | TrMoveNode | TrRemoveNode | TrSetNodeAttribute | TrRemoveNodeAttribute | TrSetNodeData | TrSetNodeScroll | TrSetInputTarget | TrSetInputValue | TrSetInputChecked | TrMouseMove | TrNetworkRequestDeprecated | TrConsoleLog | TrPageLoadTiming | TrPageRenderTiming | TrCustomEvent | TrUserID | TrUserAnonymousID | TrMetadata | TrStringDictGlobal | TrSetNodeAttributeDictGlobal | TrNodeAnimationResult | TrCSSInsertRule | TrCSSDeleteRule | TrFetch | TrProfiler | TrOTable | TrStateAction | TrReduxDeprecated | TrVuex | TrMobX | TrNgRx | TrGraphQLDeprecated | TrPerformanceTrack | TrStringDictDeprecated | TrSetNodeAttributeDictDeprecated | TrStringDict | TrSetNodeAttributeDict | TrResourceTimingDeprecatedDeprecated | TrConnectionInformation | TrSetPageVisibility | TrLoadFontFace | TrSetNodeFocus | TrLongTask | TrSetNodeAttributeURLBased | TrSetCSSDataURLBased | TrTechnicalInfo | TrCustomIssue | TrSetNodeSlot | TrCSSInsertRuleURLBased | TrMouseClick | TrMouseClickDeprecated | TrCreateIFrameDocument | TrAdoptedSSReplaceURLBased | TrAdoptedSSInsertRuleURLBased | TrAdoptedSSDeleteRule | TrAdoptedSSAddOwner | TrAdoptedSSRemoveOwner | TrJSException | TrZustand | TrBatchMetadata | TrPartitionedMessage | TrNetworkRequest | TrWSChannel | TrResourceTiming | TrIncident | TrLongAnimationTask | TrInputChange | TrSelectionChange | TrMouseThrashing | TrUnbindNodes | TrResourceTimingDeprecated | TrTabChange | TrTabData | TrCanvasNode | TrTagTrigger | TrRedux | TrSetPageLocation | TrGraphQL | TrWebVitals
|
||||
|
||||
export default function translate(tMsg: TrackerMessage): RawMessage | null {
|
||||
switch(tMsg[0]) {
|
||||
|
|
@ -799,6 +811,14 @@ export default function translate(tMsg: TrackerMessage): RawMessage | null {
|
|||
}
|
||||
}
|
||||
|
||||
case 36: {
|
||||
return {
|
||||
tp: MType.NodeAnimationResult,
|
||||
id: tMsg[1],
|
||||
styles: tMsg[2],
|
||||
}
|
||||
}
|
||||
|
||||
case 37: {
|
||||
return {
|
||||
tp: MType.CssInsertRule,
|
||||
|
|
@ -1014,6 +1034,14 @@ export default function translate(tMsg: TrackerMessage): RawMessage | null {
|
|||
}
|
||||
}
|
||||
|
||||
case 65: {
|
||||
return {
|
||||
tp: MType.SetNodeSlot,
|
||||
id: tMsg[1],
|
||||
slotID: tMsg[2],
|
||||
}
|
||||
}
|
||||
|
||||
case 67: {
|
||||
return {
|
||||
tp: MType.CssInsertRuleURLBased,
|
||||
|
|
|
|||
|
|
@ -220,6 +220,11 @@ message 35, 'SetNodeAttributeDictGlobal' do
|
|||
uint 'Value'
|
||||
end
|
||||
|
||||
message 36, 'NodeAnimationResult' do
|
||||
uint 'ID'
|
||||
string 'Styles'
|
||||
end
|
||||
|
||||
# DEPRECATED since 4.0.2 in favor of AdoptedSSInsertRule + AdoptedSSAddOwner
|
||||
message 37, 'CSSInsertRule' do
|
||||
uint 'ID'
|
||||
|
|
@ -396,7 +401,10 @@ message 64, 'CustomIssue', :replayer => false do
|
|||
string 'Name'
|
||||
string 'Payload'
|
||||
end
|
||||
|
||||
message 65, 'SetNodeSlot' do
|
||||
uint 'ID'
|
||||
uint 'SlotID'
|
||||
end
|
||||
message 66, 'AssetCache', :replayer => false, :tracker => false do
|
||||
string 'URL'
|
||||
end
|
||||
|
|
@ -659,4 +667,4 @@ message 127, 'SessionSearch', :tracker => false, :replayer => false do
|
|||
uint 'Partition'
|
||||
end
|
||||
|
||||
# FREE 2, 35, 36, 65, 87, 88, 89
|
||||
# FREE 2, 87, 88, 89
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@openreplay/tracker",
|
||||
"description": "The OpenReplay tracker main package",
|
||||
"version": "17.0.0-beta.0",
|
||||
"version": "17.1.0-beta.11",
|
||||
"keywords": [
|
||||
"logging",
|
||||
"replay"
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ export declare const enum Type {
|
|||
Metadata = 30,
|
||||
StringDictGlobal = 34,
|
||||
SetNodeAttributeDictGlobal = 35,
|
||||
NodeAnimationResult = 36,
|
||||
CSSInsertRule = 37,
|
||||
CSSDeleteRule = 38,
|
||||
Fetch = 39,
|
||||
|
|
@ -55,6 +56,7 @@ export declare const enum Type {
|
|||
SetCSSDataURLBased = 61,
|
||||
TechnicalInfo = 63,
|
||||
CustomIssue = 64,
|
||||
SetNodeSlot = 65,
|
||||
CSSInsertRuleURLBased = 67,
|
||||
MouseClick = 68,
|
||||
MouseClickDeprecated = 69,
|
||||
|
|
@ -270,6 +272,12 @@ export type SetNodeAttributeDictGlobal = [
|
|||
/*value:*/ number,
|
||||
]
|
||||
|
||||
export type NodeAnimationResult = [
|
||||
/*type:*/ Type.NodeAnimationResult,
|
||||
/*id:*/ number,
|
||||
/*styles:*/ string,
|
||||
]
|
||||
|
||||
export type CSSInsertRule = [
|
||||
/*type:*/ Type.CSSInsertRule,
|
||||
/*id:*/ number,
|
||||
|
|
@ -456,6 +464,12 @@ export type CustomIssue = [
|
|||
/*payload:*/ string,
|
||||
]
|
||||
|
||||
export type SetNodeSlot = [
|
||||
/*type:*/ Type.SetNodeSlot,
|
||||
/*id:*/ number,
|
||||
/*slotID:*/ number,
|
||||
]
|
||||
|
||||
export type CSSInsertRuleURLBased = [
|
||||
/*type:*/ Type.CSSInsertRuleURLBased,
|
||||
/*id:*/ number,
|
||||
|
|
@ -705,5 +719,5 @@ export type WebVitals = [
|
|||
]
|
||||
|
||||
|
||||
type Message = Timestamp | SetPageLocationDeprecated | SetViewportSize | SetViewportScroll | CreateDocument | CreateElementNode | CreateTextNode | MoveNode | RemoveNode | SetNodeAttribute | RemoveNodeAttribute | SetNodeData | SetNodeScroll | SetInputTarget | SetInputValue | SetInputChecked | MouseMove | NetworkRequestDeprecated | ConsoleLog | PageLoadTiming | PageRenderTiming | CustomEvent | UserID | UserAnonymousID | Metadata | StringDictGlobal | SetNodeAttributeDictGlobal | CSSInsertRule | CSSDeleteRule | Fetch | Profiler | OTable | StateAction | ReduxDeprecated | Vuex | MobX | NgRx | GraphQLDeprecated | PerformanceTrack | StringDictDeprecated | SetNodeAttributeDictDeprecated | StringDict | SetNodeAttributeDict | ResourceTimingDeprecatedDeprecated | ConnectionInformation | SetPageVisibility | LoadFontFace | SetNodeFocus | LongTask | SetNodeAttributeURLBased | SetCSSDataURLBased | TechnicalInfo | CustomIssue | CSSInsertRuleURLBased | MouseClick | MouseClickDeprecated | CreateIFrameDocument | AdoptedSSReplaceURLBased | AdoptedSSInsertRuleURLBased | AdoptedSSDeleteRule | AdoptedSSAddOwner | AdoptedSSRemoveOwner | JSException | Zustand | BatchMetadata | PartitionedMessage | NetworkRequest | WSChannel | ResourceTiming | Incident | LongAnimationTask | InputChange | SelectionChange | MouseThrashing | UnbindNodes | ResourceTimingDeprecated | TabChange | TabData | CanvasNode | TagTrigger | Redux | SetPageLocation | GraphQL | WebVitals
|
||||
type Message = Timestamp | SetPageLocationDeprecated | SetViewportSize | SetViewportScroll | CreateDocument | CreateElementNode | CreateTextNode | MoveNode | RemoveNode | SetNodeAttribute | RemoveNodeAttribute | SetNodeData | SetNodeScroll | SetInputTarget | SetInputValue | SetInputChecked | MouseMove | NetworkRequestDeprecated | ConsoleLog | PageLoadTiming | PageRenderTiming | CustomEvent | UserID | UserAnonymousID | Metadata | StringDictGlobal | SetNodeAttributeDictGlobal | NodeAnimationResult | CSSInsertRule | CSSDeleteRule | Fetch | Profiler | OTable | StateAction | ReduxDeprecated | Vuex | MobX | NgRx | GraphQLDeprecated | PerformanceTrack | StringDictDeprecated | SetNodeAttributeDictDeprecated | StringDict | SetNodeAttributeDict | ResourceTimingDeprecatedDeprecated | ConnectionInformation | SetPageVisibility | LoadFontFace | SetNodeFocus | LongTask | SetNodeAttributeURLBased | SetCSSDataURLBased | TechnicalInfo | CustomIssue | SetNodeSlot | CSSInsertRuleURLBased | MouseClick | MouseClickDeprecated | CreateIFrameDocument | AdoptedSSReplaceURLBased | AdoptedSSInsertRuleURLBased | AdoptedSSDeleteRule | AdoptedSSAddOwner | AdoptedSSRemoveOwner | JSException | Zustand | BatchMetadata | PartitionedMessage | NetworkRequest | WSChannel | ResourceTiming | Incident | LongAnimationTask | InputChange | SelectionChange | MouseThrashing | UnbindNodes | ResourceTimingDeprecated | TabChange | TabData | CanvasNode | TagTrigger | Redux | SetPageLocation | GraphQL | WebVitals
|
||||
export default Message
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ type TagTypeMap = {
|
|||
style: HTMLStyleElement | SVGStyleElement
|
||||
link: HTMLLinkElement
|
||||
canvas: HTMLCanvasElement
|
||||
slot: HTMLSlotElement
|
||||
}
|
||||
export function hasTag<T extends keyof TagTypeMap>(
|
||||
el: Node,
|
||||
|
|
|
|||
|
|
@ -340,6 +340,17 @@ export function SetNodeAttributeDictGlobal(
|
|||
]
|
||||
}
|
||||
|
||||
export function NodeAnimationResult(
|
||||
id: number,
|
||||
styles: string,
|
||||
): Messages.NodeAnimationResult {
|
||||
return [
|
||||
Messages.Type.NodeAnimationResult,
|
||||
id,
|
||||
styles,
|
||||
]
|
||||
}
|
||||
|
||||
export function CSSInsertRule(
|
||||
id: number,
|
||||
rule: string,
|
||||
|
|
@ -686,6 +697,17 @@ export function CustomIssue(
|
|||
]
|
||||
}
|
||||
|
||||
export function SetNodeSlot(
|
||||
id: number,
|
||||
slotID: number,
|
||||
): Messages.SetNodeSlot {
|
||||
return [
|
||||
Messages.Type.SetNodeSlot,
|
||||
id,
|
||||
slotID,
|
||||
]
|
||||
}
|
||||
|
||||
export function CSSInsertRuleURLBased(
|
||||
id: number,
|
||||
rule: string,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ import {
|
|||
UnbindNodes,
|
||||
SetNodeAttribute,
|
||||
AdoptedSSInsertRuleURLBased,
|
||||
AdoptedSSAddOwner
|
||||
AdoptedSSAddOwner,
|
||||
SetNodeSlot,
|
||||
} from '../messages.gen.js'
|
||||
import App from '../index.js'
|
||||
import {
|
||||
|
|
@ -199,6 +200,7 @@ export default abstract class Observer {
|
|||
private readonly indexes: Array<number> = []
|
||||
private readonly attributesMap: Map<number, Set<string>> = new Map()
|
||||
private readonly textSet: Set<number> = new Set()
|
||||
private readonly slotMap: Map<number, number | undefined> = new Map()
|
||||
private readonly disableSprites: boolean = false
|
||||
/**
|
||||
* this option means that, instead of using link element with href to load css,
|
||||
|
|
@ -428,6 +430,18 @@ export default abstract class Observer {
|
|||
|
||||
private bindNode(node: Node): void {
|
||||
const [id, isNew] = this.app.nodes.registerNode(node)
|
||||
if (isElementNode(node) && hasTag(node, 'slot')) {
|
||||
this.app.nodes.attachNodeListener(node, 'slotchange', () => {
|
||||
const sl = node as HTMLSlotElement
|
||||
sl.assignedNodes({ flatten: true }).forEach((n) => {
|
||||
const nid = this.app.nodes.getID(n)
|
||||
if (nid !== undefined) {
|
||||
this.recents.set(nid, RecentsType.Removed)
|
||||
this.commitNode(nid)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
if (isNew) {
|
||||
this.recents.set(id, RecentsType.New)
|
||||
} else if (this.recents.get(id) !== RecentsType.New) {
|
||||
|
|
@ -463,6 +477,9 @@ export default abstract class Observer {
|
|||
|
||||
private unbindTree(node: Node) {
|
||||
const id = this.app.nodes.unregisterNode(node)
|
||||
if (id !== undefined) {
|
||||
this.slotMap.delete(id)
|
||||
}
|
||||
if (id !== undefined && this.recents.get(id) === RecentsType.Removed) {
|
||||
// Sending RemoveNode only for parent to maintain
|
||||
this.app.send(RemoveNode(id))
|
||||
|
|
@ -501,8 +518,8 @@ export default abstract class Observer {
|
|||
if (isRootNode(node)) {
|
||||
return true
|
||||
}
|
||||
// @ts-ignore SALESFORCE
|
||||
const parent = node.assignedSlot ? node.assignedSlot : node.parentNode
|
||||
const slot = (node as any).assignedSlot as HTMLSlotElement | null
|
||||
const parent = node.parentNode
|
||||
let parentID: number | undefined
|
||||
|
||||
// Disable parent check for the upper context HTMLHtmlElement, because it is root there... (before)
|
||||
|
|
@ -576,10 +593,27 @@ export default abstract class Observer {
|
|||
this.app.send(CreateTextNode(id, parentID as number, index))
|
||||
this.throttledSetNodeData(id, parent as Element, node.data)
|
||||
}
|
||||
if (slot) {
|
||||
const slotID = this.app.nodes.getID(slot)
|
||||
if (slotID !== undefined) {
|
||||
this.slotMap.set(id, slotID)
|
||||
this.app.send(SetNodeSlot(id, slotID))
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (recentsType === RecentsType.Removed && parentID !== undefined) {
|
||||
this.app.send(MoveNode(id, parentID, index))
|
||||
if (slot) {
|
||||
const slotID = this.app.nodes.getID(slot)
|
||||
if (slotID !== undefined && this.slotMap.get(id) !== slotID) {
|
||||
this.slotMap.set(id, slotID)
|
||||
this.app.send(SetNodeSlot(id, slotID))
|
||||
}
|
||||
} else if (this.slotMap.has(id)) {
|
||||
this.slotMap.delete(id)
|
||||
this.app.send(SetNodeSlot(id, 0))
|
||||
}
|
||||
}
|
||||
const attr = this.attributesMap.get(id)
|
||||
if (attr !== undefined) {
|
||||
|
|
|
|||
|
|
@ -29,9 +29,11 @@ import ConstructedStyleSheets from './modules/constructedStyleSheets.js'
|
|||
import Selection from './modules/selection.js'
|
||||
import Tabs from './modules/tabs.js'
|
||||
import LongAnimationTask from "./modules/longAnimationTask.js";
|
||||
import FeatureFlags, { IFeatureFlag } from './modules/featureFlags.js'
|
||||
import WebAnimations from './modules/webAnimations.js'
|
||||
|
||||
import { IN_BROWSER, deprecationWarn, DOCS_HOST, inIframe } from './utils.js'
|
||||
import FeatureFlags, { IFeatureFlag } from './modules/featureFlags.js'
|
||||
|
||||
import type { Options as AppOptions } from './app/index.js'
|
||||
import type { Options as ConsoleOptions } from './modules/console.js'
|
||||
import type { Options as ExceptionOptions } from './modules/exception.js'
|
||||
|
|
@ -43,6 +45,7 @@ import type { MouseHandlerOptions } from './modules/mouse.js'
|
|||
import type { SessionInfo } from './app/session.js'
|
||||
import type { CssRulesOptions } from './modules/cssrules.js'
|
||||
import type { LATOptions } from './modules/longAnimationTask.js'
|
||||
import type { Options as WapOptions } from './modules/webAnimations.js'
|
||||
|
||||
import type { StartOptions } from './app/index.js'
|
||||
//TODO: unique options init
|
||||
|
|
@ -71,6 +74,7 @@ export type Options = Partial<
|
|||
// dev only
|
||||
__DISABLE_SECURE_MODE?: boolean
|
||||
css: CssRulesOptions
|
||||
webAnimations?: WapOptions
|
||||
}
|
||||
|
||||
const DOCS_SETUP = '/en/sdk'
|
||||
|
|
@ -217,6 +221,7 @@ export default class API {
|
|||
Network(app, options.network)
|
||||
}
|
||||
Selection(app)
|
||||
WebAnimations(app, options.webAnimations)
|
||||
;(window as any).__OPENREPLAY__ = this
|
||||
|
||||
if (options.flags && options.flags.onFlagsLoad) {
|
||||
|
|
|
|||
69
tracker/tracker/src/main/modules/webAnimations.ts
Normal file
69
tracker/tracker/src/main/modules/webAnimations.ts
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
import type App from '../app/index.js'
|
||||
import { NodeAnimationResult } from '../app/messages.gen.js'
|
||||
|
||||
/**
|
||||
* this will only work for custom elements by default (because of ionic)
|
||||
*/
|
||||
|
||||
export interface Options {
|
||||
allElements?: boolean
|
||||
}
|
||||
|
||||
const toIgnore = ["composite", "computedOffset", "easing", "offset"]
|
||||
|
||||
function webAnimations(app: App, options: Options = {}) {
|
||||
const { allElements = false } = options
|
||||
let listening = new WeakSet<Node>()
|
||||
let handled = new WeakSet()
|
||||
function wire(anim, el, nodeId) {
|
||||
if (handled.has(anim)) return
|
||||
handled.add(anim)
|
||||
|
||||
anim.addEventListener(
|
||||
'finish',
|
||||
() => {
|
||||
const lastKF = anim.effect.getKeyframes().at(-1)
|
||||
const computedStyle = getComputedStyle(el)
|
||||
const keys = Object.keys(lastKF).filter((p) => !toIgnore.includes(p))
|
||||
// @ts-ignore
|
||||
const finalStyle = {}
|
||||
keys.forEach((key) => {
|
||||
finalStyle[key] = computedStyle[key]
|
||||
})
|
||||
app.send(NodeAnimationResult(nodeId, JSON.stringify(finalStyle)))
|
||||
},
|
||||
{ once: true },
|
||||
)
|
||||
}
|
||||
|
||||
function scanElement(el, nodeId) {
|
||||
el.getAnimations({ subtree: false }).forEach((anim) => wire(anim, el, nodeId))
|
||||
}
|
||||
|
||||
app.nodes.attachNodeCallback((node) => {
|
||||
if ((allElements || node.nodeName.includes('-')) && 'getAnimations' in node) {
|
||||
const animations = (node as Element).getAnimations({ subtree: false })
|
||||
const id = app.nodes.getID(node)
|
||||
if (animations.length > 0 && !listening.has(node) && id) {
|
||||
listening.add(node)
|
||||
scanElement(node, id)
|
||||
node.addEventListener('animationstart', () => scanElement(node, id))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const origAnimate = Element.prototype.animate
|
||||
Element.prototype.animate = function (...args) {
|
||||
const anim = origAnimate.apply(this, args)
|
||||
wire(anim, this)
|
||||
return anim
|
||||
}
|
||||
|
||||
app.attachStopCallback(() => {
|
||||
Element.prototype.animate = origAnimate // Restore original animate method
|
||||
listening = new WeakSet<Node>()
|
||||
handled = new WeakSet()
|
||||
})
|
||||
}
|
||||
|
||||
export default webAnimations
|
||||
|
|
@ -118,6 +118,10 @@ export default class MessageEncoder extends PrimitiveEncoder {
|
|||
return this.uint(msg[1]) && this.uint(msg[2]) && this.uint(msg[3])
|
||||
break
|
||||
|
||||
case Messages.Type.NodeAnimationResult:
|
||||
return this.uint(msg[1]) && this.string(msg[2])
|
||||
break
|
||||
|
||||
case Messages.Type.CSSInsertRule:
|
||||
return this.uint(msg[1]) && this.string(msg[2]) && this.uint(msg[3])
|
||||
break
|
||||
|
|
@ -222,6 +226,10 @@ export default class MessageEncoder extends PrimitiveEncoder {
|
|||
return this.string(msg[1]) && this.string(msg[2])
|
||||
break
|
||||
|
||||
case Messages.Type.SetNodeSlot:
|
||||
return this.uint(msg[1]) && this.uint(msg[2])
|
||||
break
|
||||
|
||||
case Messages.Type.CSSInsertRuleURLBased:
|
||||
return this.uint(msg[1]) && this.string(msg[2]) && this.uint(msg[3]) && this.string(msg[4])
|
||||
break
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue