mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
1f151e0d2f
Summary: changelog: backout Original commit changeset: a1530cc6e2a9 Original Phabricator Diff: D43180893 (https://github.com/facebook/react-native/commit/89ef5bd6f9064298dfe55b0b18be4a770ee0872c) Reviewed By: Andjeliko, javache Differential Revision: D43350025 fbshipit-source-id: 896057e16c2f466b2ecf2da6b38c56963dc51020
164 lines
4.7 KiB
JavaScript
164 lines
4.7 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow strict-local
|
|
* @format
|
|
*/
|
|
|
|
import type {Overlay} from './TraceUpdateOverlayNativeComponent';
|
|
|
|
import processColor from '../../StyleSheet/processColor';
|
|
import StyleSheet from '../../StyleSheet/StyleSheet';
|
|
import View from '../View/View';
|
|
import TraceUpdateOverlayNativeComponent, {
|
|
Commands,
|
|
} from './TraceUpdateOverlayNativeComponent';
|
|
import * as React from 'react';
|
|
|
|
type AgentEvents = {
|
|
drawTraceUpdates: [Array<{node: TraceNode, color: string}>],
|
|
disableTraceUpdates: [],
|
|
};
|
|
|
|
interface Agent {
|
|
addListener<Event: $Keys<AgentEvents>>(
|
|
event: Event,
|
|
listener: (...AgentEvents[Event]) => void,
|
|
): void;
|
|
removeListener(event: $Keys<AgentEvents>, listener: () => void): void;
|
|
}
|
|
|
|
type TraceNode = {
|
|
canonical?: TraceNode,
|
|
measure?: (
|
|
(
|
|
x: number,
|
|
y: number,
|
|
width: number,
|
|
height: number,
|
|
left: number,
|
|
top: number,
|
|
) => void,
|
|
) => void,
|
|
};
|
|
|
|
type ReactDevToolsGlobalHook = {
|
|
on: (eventName: string, (agent: Agent) => void) => void,
|
|
off: (eventName: string, (agent: Agent) => void) => void,
|
|
reactDevtoolsAgent: Agent,
|
|
};
|
|
|
|
const {useEffect, useRef, useState} = React;
|
|
const hook: ReactDevToolsGlobalHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
let devToolsAgent: ?Agent;
|
|
|
|
export default function TraceUpdateOverlay(): React.Node {
|
|
const [overlayDisabled, setOverlayDisabled] = useState(false);
|
|
// This effect is designed to be explictly shown here to avoid re-subscribe from the same
|
|
// overlay component.
|
|
useEffect(() => {
|
|
function attachToDevtools(agent: Agent) {
|
|
devToolsAgent = agent;
|
|
agent.addListener('drawTraceUpdates', onAgentDrawTraceUpdates);
|
|
agent.addListener('disableTraceUpdates', onAgentDisableTraceUpdates);
|
|
}
|
|
|
|
function subscribe() {
|
|
hook?.on('react-devtools', attachToDevtools);
|
|
if (hook?.reactDevtoolsAgent) {
|
|
attachToDevtools(hook.reactDevtoolsAgent);
|
|
}
|
|
}
|
|
|
|
function unsubscribe() {
|
|
hook?.off('react-devtools', attachToDevtools);
|
|
const agent = devToolsAgent;
|
|
if (agent != null) {
|
|
agent.removeListener('drawTraceUpdates', onAgentDrawTraceUpdates);
|
|
agent.removeListener('disableTraceUpdates', onAgentDisableTraceUpdates);
|
|
devToolsAgent = null;
|
|
}
|
|
}
|
|
|
|
function onAgentDrawTraceUpdates(
|
|
nodesToDraw: Array<{node: TraceNode, color: string}> = [],
|
|
) {
|
|
// If overlay is disabled before, now it's enabled.
|
|
setOverlayDisabled(false);
|
|
|
|
const newFramesToDraw: Array<Promise<Overlay>> = [];
|
|
nodesToDraw.forEach(({node, color}) => {
|
|
const component = node.canonical ?? node;
|
|
if (!component || !component.measure) {
|
|
return;
|
|
}
|
|
const frameToDrawPromise = new Promise<Overlay>(resolve => {
|
|
// The if statement here is to make flow happy
|
|
if (component.measure) {
|
|
// TODO(T145522797): We should refactor this to use `getBoundingClientRect` when Paper is no longer supported.
|
|
component.measure((x, y, width, height, left, top) => {
|
|
resolve({
|
|
rect: {left, top, width, height},
|
|
color: processColor(color),
|
|
});
|
|
});
|
|
}
|
|
});
|
|
newFramesToDraw.push(frameToDrawPromise);
|
|
});
|
|
Promise.all(newFramesToDraw).then(
|
|
results => {
|
|
if (nativeComponentRef.current != null) {
|
|
Commands.draw(
|
|
nativeComponentRef.current,
|
|
JSON.stringify(
|
|
results.filter(
|
|
({rect, color}) => rect.width >= 0 && rect.height >= 0,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
},
|
|
err => {
|
|
console.error(`Failed to measure updated traces. Error: ${err}`);
|
|
},
|
|
);
|
|
}
|
|
|
|
function onAgentDisableTraceUpdates() {
|
|
// When trace updates are disabled from the backend, we won't receive draw events until it's enabled by the next draw. We can safely remove the overlay as it's not needed now.
|
|
setOverlayDisabled(true);
|
|
}
|
|
|
|
subscribe();
|
|
return unsubscribe;
|
|
}, []); // Only run once when the overlay initially rendered
|
|
|
|
const nativeComponentRef =
|
|
useRef<?React.ElementRef<typeof TraceUpdateOverlayNativeComponent>>(null);
|
|
|
|
return (
|
|
!overlayDisabled && (
|
|
<View pointerEvents="none" style={styles.overlay}>
|
|
<TraceUpdateOverlayNativeComponent
|
|
ref={nativeComponentRef}
|
|
style={styles.overlay}
|
|
/>
|
|
</View>
|
|
)
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
overlay: {
|
|
position: 'absolute',
|
|
top: 0,
|
|
bottom: 0,
|
|
left: 0,
|
|
right: 0,
|
|
},
|
|
});
|