[Dev] Teact: Add debug overlay
This commit is contained in:
parent
07e7253b02
commit
56dbad1ef9
@ -1,7 +1,7 @@
|
|||||||
import { useCallback, useState } from '../lib/teact/teact';
|
import { useCallback, useState } from '../lib/teact/teact';
|
||||||
|
|
||||||
const useFlag = (initial = false): [boolean, NoneToVoidFunction, NoneToVoidFunction] => {
|
const useFlag = (initial = false, debugKey?: string): [boolean, NoneToVoidFunction, NoneToVoidFunction] => {
|
||||||
const [value, setValue] = useState(initial);
|
const [value, setValue] = useState(initial, debugKey);
|
||||||
|
|
||||||
const setTrue = useCallback(() => {
|
const setTrue = useCallback(() => {
|
||||||
setValue(true);
|
setValue(true);
|
||||||
|
|||||||
@ -6,13 +6,12 @@ import {
|
|||||||
import { orderBy } from '../../util/iteratees';
|
import { orderBy } from '../../util/iteratees';
|
||||||
import { getUnequalProps } from '../../util/arePropsShallowEqual';
|
import { getUnequalProps } from '../../util/arePropsShallowEqual';
|
||||||
import { handleError } from '../../util/handleError';
|
import { handleError } from '../../util/handleError';
|
||||||
|
import { incrementOverlayCounter } from '../../util/debugOverlay';
|
||||||
|
|
||||||
export type Props = AnyLiteral;
|
export type Props = AnyLiteral;
|
||||||
export type FC<P extends Props = any> = (props: P) => any;
|
export type FC<P extends Props = any> = (props: P) => any;
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
export type FC_withDebug = FC & {
|
export type FC_withDebug = FC & { DEBUG_contentComponentName?: string };
|
||||||
DEBUG_contentComponentName?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export enum VirtualElementTypesEnum {
|
export enum VirtualElementTypesEnum {
|
||||||
Empty,
|
Empty,
|
||||||
@ -339,6 +338,11 @@ export function renderComponent(componentInstance: ComponentInstance) {
|
|||||||
}
|
}
|
||||||
DEBUG_components[componentName].renderTimes.push(duration);
|
DEBUG_components[componentName].renderTimes.push(duration);
|
||||||
DEBUG_components[componentName].renderCount++;
|
DEBUG_components[componentName].renderCount++;
|
||||||
|
|
||||||
|
if (DEBUG_MORE) {
|
||||||
|
incrementOverlayCounter(`${componentName} renders`);
|
||||||
|
incrementOverlayCounter(`${componentName} duration`, duration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
handleError(err);
|
handleError(err);
|
||||||
|
|||||||
109
src/util/debugOverlay.ts
Normal file
109
src/util/debugOverlay.ts
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
import { throttle } from './schedulers';
|
||||||
|
|
||||||
|
const KEYS_TO_IGNORE = new Set([
|
||||||
|
'TeactMemoWrapper renders',
|
||||||
|
'TeactNContainer renders',
|
||||||
|
'Button renders',
|
||||||
|
]);
|
||||||
|
const MIN_RENDERS_TO_SHOW = 5;
|
||||||
|
const MIN_DURATION_TO_SHOW = 2;
|
||||||
|
const BG_GREEN = ' style="background: lightgreen"';
|
||||||
|
|
||||||
|
let counters: Record<string, {
|
||||||
|
value: number;
|
||||||
|
lastUpdateAt: number;
|
||||||
|
}> = {};
|
||||||
|
|
||||||
|
const renderCountersThrottled = throttle(renderCounters, 500, false);
|
||||||
|
|
||||||
|
let loggerEl: HTMLDivElement;
|
||||||
|
|
||||||
|
export function debugToOverlay(text: string) {
|
||||||
|
if (!loggerEl) {
|
||||||
|
setupOverlay();
|
||||||
|
}
|
||||||
|
|
||||||
|
const date = new Date();
|
||||||
|
const dateFormatted = `${date.toLocaleTimeString()}.${date.getMilliseconds()}`;
|
||||||
|
const wasAtBottom = loggerEl.scrollTop + 10 >= loggerEl.scrollHeight - loggerEl.offsetHeight;
|
||||||
|
|
||||||
|
loggerEl.innerHTML += `${dateFormatted}: ${text}<br/>`;
|
||||||
|
|
||||||
|
if (wasAtBottom) {
|
||||||
|
loggerEl.scrollTop = loggerEl.scrollHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function incrementOverlayCounter(key: string, value = 1) {
|
||||||
|
const now = Date.now();
|
||||||
|
if (!counters[key]) {
|
||||||
|
counters[key] = { value, lastUpdateAt: now };
|
||||||
|
} else {
|
||||||
|
counters[key].value += value;
|
||||||
|
counters[key].lastUpdateAt = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderCountersThrottled();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderCounters() {
|
||||||
|
if (!loggerEl) {
|
||||||
|
setupOverlay();
|
||||||
|
}
|
||||||
|
|
||||||
|
const halfSecondAgo = Date.now() - 500;
|
||||||
|
const [maxRenders, maxDuration] = Object.entries(counters).reduce((acc, [key, { value }]) => {
|
||||||
|
if (KEYS_TO_IGNORE.has(key)) {
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key.includes('renders') && value > acc[0]) {
|
||||||
|
acc[0] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key.includes('duration') && value > acc[1]) {
|
||||||
|
acc[1] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, [0, 0]);
|
||||||
|
|
||||||
|
loggerEl.innerHTML = Object
|
||||||
|
.entries(counters)
|
||||||
|
.filter(([key, { value }]) => (
|
||||||
|
(!KEYS_TO_IGNORE.has(key)) && (
|
||||||
|
(key.includes('renders') && value > MIN_RENDERS_TO_SHOW)
|
||||||
|
|| (key.includes('duration') && value > MIN_DURATION_TO_SHOW)
|
||||||
|
)
|
||||||
|
))
|
||||||
|
.sort((a, b) => (
|
||||||
|
b[1].lastUpdateAt - a[1].lastUpdateAt
|
||||||
|
))
|
||||||
|
.map(([key, { value, lastUpdateAt }]) => ([
|
||||||
|
`<div style="background: #ff0000${factorToHex(value / (key.includes('renders') ? maxRenders : maxDuration))}">`,
|
||||||
|
` <span${lastUpdateAt > halfSecondAgo ? BG_GREEN : ''}>${key}: ${Math.round(value)}</span>`,
|
||||||
|
'</div>',
|
||||||
|
].join('\n')))
|
||||||
|
.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupOverlay() {
|
||||||
|
loggerEl = document.createElement('div');
|
||||||
|
loggerEl.style.cssText = 'position: absolute; left: 0; bottom: 25px; z-index: 9998; width: 260px; height: 200px;'
|
||||||
|
+ ' border: 1px solid #555; background: rgba(255, 255, 255, 0.9); overflow: auto; font-size: 10px;';
|
||||||
|
document.body.appendChild(loggerEl);
|
||||||
|
|
||||||
|
const clearEl = document.createElement('a');
|
||||||
|
clearEl.style.cssText = 'position: absolute; left: 222px; bottom: 198px; z-index: 9999; font-size: 20px; '
|
||||||
|
+ 'cursor: pointer;';
|
||||||
|
clearEl.innerText = '🔄';
|
||||||
|
clearEl.addEventListener('click', () => {
|
||||||
|
counters = {};
|
||||||
|
renderCountersThrottled();
|
||||||
|
});
|
||||||
|
document.body.appendChild(clearEl);
|
||||||
|
}
|
||||||
|
|
||||||
|
function factorToHex(factor: number) {
|
||||||
|
return Math.round(255 * factor).toString(16).padStart(2, '0');
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user