Recording addEventListener spy
This commit is contained in:
parent
712f267519
commit
624500b091
@ -32,7 +32,7 @@ import {
|
|||||||
isDevEnv,
|
isDevEnv,
|
||||||
} from "@excalidraw/common";
|
} from "@excalidraw/common";
|
||||||
import polyfill from "@excalidraw/excalidraw/polyfill";
|
import polyfill from "@excalidraw/excalidraw/polyfill";
|
||||||
import { useCallback, useEffect, useRef, useState } from "react";
|
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||||
import { loadFromBlob } from "@excalidraw/excalidraw/data/blob";
|
import { loadFromBlob } from "@excalidraw/excalidraw/data/blob";
|
||||||
import { useCallbackRefState } from "@excalidraw/excalidraw/hooks/useCallbackRefState";
|
import { useCallbackRefState } from "@excalidraw/excalidraw/hooks/useCallbackRefState";
|
||||||
import { t } from "@excalidraw/excalidraw/i18n";
|
import { t } from "@excalidraw/excalidraw/i18n";
|
||||||
@ -1147,6 +1147,100 @@ const ExcalidrawWrapper = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ExcalidrawRecorderWrapper = ({ children }: React.PropsWithChildren) => {
|
||||||
|
const listenerRef = useRef<
|
||||||
|
WeakMap<
|
||||||
|
EventListenerOrEventListenerObject,
|
||||||
|
{ type: string; listener: EventListener }
|
||||||
|
>
|
||||||
|
>(new WeakMap());
|
||||||
|
const dataRef = useRef<object[]>([]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
dataRef.current.push({
|
||||||
|
time: new Date().getTime(),
|
||||||
|
type: "start",
|
||||||
|
localStorage: JSON.parse(JSON.stringify(window.localStorage)),
|
||||||
|
dimensions: {
|
||||||
|
outerWidth: window.outerWidth,
|
||||||
|
outerHeight: window.outerHeight,
|
||||||
|
},
|
||||||
|
chromeVersion: window.navigator.userAgent
|
||||||
|
.split(" ")
|
||||||
|
.find((v) => v.startsWith("Chrome/"))
|
||||||
|
?.substring(7),
|
||||||
|
});
|
||||||
|
|
||||||
|
Window.prototype._removeEventListener =
|
||||||
|
Window.prototype.removeEventListener;
|
||||||
|
window.removeEventListener = function <K extends keyof WindowEventMap>(
|
||||||
|
type: K,
|
||||||
|
listener: EventListenerOrEventListenerObject,
|
||||||
|
options?: boolean | EventListenerOptions,
|
||||||
|
) {
|
||||||
|
const existing = listenerRef.current.get(listener);
|
||||||
|
if (existing) {
|
||||||
|
window._removeEventListener(type, existing.listener, options);
|
||||||
|
listenerRef.current.delete(listener);
|
||||||
|
} else {
|
||||||
|
window._removeEventListener(type, listener, options);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Window.prototype._addEventListener = Window.prototype.addEventListener;
|
||||||
|
window.addEventListener = function <K extends keyof WindowEventMap>(
|
||||||
|
type: K,
|
||||||
|
listener: EventListenerOrEventListenerObject,
|
||||||
|
options?: boolean | AddEventListenerOptions,
|
||||||
|
) {
|
||||||
|
const existing = listenerRef.current.get(listener);
|
||||||
|
let wrappedListener: EventListener;
|
||||||
|
|
||||||
|
if (!existing || existing?.type !== type) {
|
||||||
|
wrappedListener = function (...args) {
|
||||||
|
dataRef.current.push({
|
||||||
|
time: new Date().getTime(),
|
||||||
|
type: "event",
|
||||||
|
name: type,
|
||||||
|
args,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (listener instanceof Function) {
|
||||||
|
listener.apply(window, args);
|
||||||
|
} else {
|
||||||
|
listener.handleEvent.apply(window, args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
wrappedListener = existing.listener;
|
||||||
|
window._removeEventListener(type, wrappedListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
listenerRef.current.set(listener, { type, listener: wrappedListener });
|
||||||
|
|
||||||
|
window._addEventListener(type, wrappedListener, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
Window.prototype.removeEventListener =
|
||||||
|
Window.prototype._removeEventListener;
|
||||||
|
Window.prototype.addEventListener = Window.prototype._addEventListener;
|
||||||
|
dataRef.current = [];
|
||||||
|
window.gc?.();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const handle = setInterval(() => {
|
||||||
|
console.log(dataRef.current);
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
return () => clearInterval(handle);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return <>{children}</>;
|
||||||
|
};
|
||||||
|
|
||||||
const ExcalidrawApp = () => {
|
const ExcalidrawApp = () => {
|
||||||
const isCloudExportWindow =
|
const isCloudExportWindow =
|
||||||
window.location.pathname === "/excalidraw-plus-export";
|
window.location.pathname === "/excalidraw-plus-export";
|
||||||
@ -1155,11 +1249,13 @@ const ExcalidrawApp = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TopErrorBoundary>
|
<ExcalidrawRecorderWrapper>
|
||||||
<Provider store={appJotaiStore}>
|
<TopErrorBoundary>
|
||||||
<ExcalidrawWrapper />
|
<Provider store={appJotaiStore}>
|
||||||
</Provider>
|
<ExcalidrawWrapper />
|
||||||
</TopErrorBoundary>
|
</Provider>
|
||||||
|
</TopErrorBoundary>
|
||||||
|
</ExcalidrawRecorderWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11425,6 +11425,8 @@ declare global {
|
|||||||
history: History;
|
history: History;
|
||||||
store: Store;
|
store: Store;
|
||||||
};
|
};
|
||||||
|
_addEventListener: typeof window.addEventListener;
|
||||||
|
_removeEventListener: typeof window.removeEventListener;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user