Add userTriggered (#495)
* add `userTriggered` * update snapshots to add userTriggered * add `userTriggered` * update snapshots to add userTriggered * update snapshot to include userTrigger * only set userTriggered on `userTriggeredOnInput: true` * What is user triggered? * correct snapshot * add second radio to demonstrate userTriggered
This commit is contained in:
@@ -57,6 +57,7 @@ function record<T = eventWithTime>(
|
||||
sampling = {},
|
||||
mousemoveWait,
|
||||
recordCanvas = false,
|
||||
userTriggeredOnInput = false,
|
||||
collectFonts = false,
|
||||
plugins,
|
||||
keepIframeSrcFn = () => false,
|
||||
@@ -379,6 +380,7 @@ function record<T = eventWithTime>(
|
||||
inlineStylesheet,
|
||||
sampling,
|
||||
recordCanvas,
|
||||
userTriggeredOnInput,
|
||||
collectFonts,
|
||||
doc,
|
||||
maskInputFn,
|
||||
|
||||
@@ -337,6 +337,15 @@ function initViewportResizeObserver(
|
||||
return on('resize', updateDimension, window);
|
||||
}
|
||||
|
||||
function wrapEventWithUserTriggeredFlag(
|
||||
v: inputValue,
|
||||
enable: boolean,
|
||||
): inputValue {
|
||||
const value = { ...v };
|
||||
if (!enable) delete value.userTriggered;
|
||||
return value;
|
||||
}
|
||||
|
||||
export const INPUT_TAGS = ['INPUT', 'TEXTAREA', 'SELECT'];
|
||||
const lastInputValueMap: WeakMap<EventTarget, inputValue> = new WeakMap();
|
||||
function initInputObserver(
|
||||
@@ -348,9 +357,11 @@ function initInputObserver(
|
||||
maskInputOptions: MaskInputOptions,
|
||||
maskInputFn: MaskInputFn | undefined,
|
||||
sampling: SamplingStrategy,
|
||||
userTriggeredOnInput: boolean,
|
||||
): listenerHandler {
|
||||
function eventHandler(event: Event) {
|
||||
const target = getEventTarget(event);
|
||||
const userTriggered = event.isTrusted;
|
||||
if (
|
||||
!target ||
|
||||
!(target as Element).tagName ||
|
||||
@@ -381,7 +392,13 @@ function initInputObserver(
|
||||
maskInputFn,
|
||||
});
|
||||
}
|
||||
cbWithDedup(target, { text, isChecked });
|
||||
cbWithDedup(
|
||||
target,
|
||||
wrapEventWithUserTriggeredFlag(
|
||||
{ text, isChecked, userTriggered },
|
||||
userTriggeredOnInput,
|
||||
),
|
||||
);
|
||||
// if a radio was checked
|
||||
// the other radios with the same name attribute will be unchecked.
|
||||
const name: string | undefined = (target as HTMLInputElement).name;
|
||||
@@ -390,10 +407,17 @@ function initInputObserver(
|
||||
.querySelectorAll(`input[type="radio"][name="${name}"]`)
|
||||
.forEach((el) => {
|
||||
if (el !== target) {
|
||||
cbWithDedup(el, {
|
||||
text: (el as HTMLInputElement).value,
|
||||
isChecked: !isChecked,
|
||||
});
|
||||
cbWithDedup(
|
||||
el,
|
||||
wrapEventWithUserTriggeredFlag(
|
||||
{
|
||||
text: (el as HTMLInputElement).value,
|
||||
isChecked: !isChecked,
|
||||
userTriggered: false,
|
||||
},
|
||||
userTriggeredOnInput,
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -763,6 +787,7 @@ export function initObservers(
|
||||
o.maskInputOptions,
|
||||
o.maskInputFn,
|
||||
o.sampling,
|
||||
o.userTriggeredOnInput,
|
||||
);
|
||||
const mediaInteractionHandler = initMediaInteractionObserver(
|
||||
o.mediaInteractionCb,
|
||||
|
||||
@@ -115,6 +115,7 @@ export class Replayer {
|
||||
triggerFocus: true,
|
||||
UNSAFE_replayCanvas: false,
|
||||
pauseAnimation: true,
|
||||
userTriggeredOnInput: true,
|
||||
mouseTail: defaultMouseTailConfig,
|
||||
};
|
||||
this.config = Object.assign({}, defaultConfig, config);
|
||||
@@ -501,10 +502,7 @@ export class Replayer {
|
||||
|
||||
// events are kept sorted by timestamp, check if this is the last event
|
||||
let last_index = this.service.state.context.events.length - 1;
|
||||
if (
|
||||
event ===
|
||||
this.service.state.context.events[last_index]
|
||||
) {
|
||||
if (event === this.service.state.context.events[last_index]) {
|
||||
const finish = () => {
|
||||
if (last_index < this.service.state.context.events.length - 1) {
|
||||
// more events have been added since the setTimeout
|
||||
|
||||
@@ -218,6 +218,7 @@ export type recordOptions<T> = {
|
||||
packFn?: PackFn;
|
||||
sampling?: SamplingStrategy;
|
||||
recordCanvas?: boolean;
|
||||
userTriggeredOnInput?: boolean;
|
||||
collectFonts?: boolean;
|
||||
plugins?: RecordPlugin[];
|
||||
// departed, please use sampling options
|
||||
@@ -247,6 +248,7 @@ export type observerParam = {
|
||||
fontCb: fontCallback;
|
||||
sampling: SamplingStrategy;
|
||||
recordCanvas: boolean;
|
||||
userTriggeredOnInput: boolean;
|
||||
collectFonts: boolean;
|
||||
slimDOMOptions: SlimDOMOptions;
|
||||
doc: Document;
|
||||
@@ -419,6 +421,12 @@ export type viewportResizeCallback = (d: viewportResizeDimension) => void;
|
||||
export type inputValue = {
|
||||
text: string;
|
||||
isChecked: boolean;
|
||||
|
||||
// `userTriggered` indicates if this event was triggered directly by user (userTriggered: true)
|
||||
// or was triggered indirectly (userTriggered: false)
|
||||
// Example of `userTriggered` in action:
|
||||
// User clicks on radio element (userTriggered: true) which triggers the other radio element to change (userTriggered: false)
|
||||
userTriggered?: boolean;
|
||||
};
|
||||
|
||||
export type inputCallback = (v: inputValue & { id: number }) => void;
|
||||
@@ -484,6 +492,7 @@ export type playerConfig = {
|
||||
triggerFocus: boolean;
|
||||
UNSAFE_replayCanvas: boolean;
|
||||
pauseAnimation?: boolean;
|
||||
userTriggeredOnInput: boolean;
|
||||
mouseTail:
|
||||
| boolean
|
||||
| {
|
||||
|
||||
Reference in New Issue
Block a user