Files
react-native/Libraries/Inspector/DevtoolsHighlighter.js
T
Tianyu Yao a63204800a Show highlight when element is selected in React devtools
Summary:
Changelog:
[General][Changed] - Copied and refactored the current devtools highlighting code from Inspector into its own module and add to the top level `AppContainer`. The effect is that the highlight stills shows without Inspector opened.

This diff copies the current devtools highlighting logic from Inspector into a module and add to the top level `AppContainer`. The effect is without Inspector opened, the highlight will still show.

## Context
This is the first diff for "Component Tab Automatically Highlight Elements". The idea is to replicate the behavior on Web to RN.

## Behavior
on Web:
- highlight shows whenever an element in the component list is hovered
- Selecting an element doesn't keeps the highlight showing.

on RN (before this diff):
- when RN inspector opens: selecting an element keeps the highlight showing
- when RN inspector closes: stop showing highlihgintg.

on RN(this diff)
- selecting an element keeps the highlight showing

## TODO
- See if highlighting event can be sent on hover, instead of when an element is selected.

Reviewed By: lunaruan

Differential Revision: D38568135

fbshipit-source-id: d168874677d08a9c5526a7f896943579da804565
2022-08-16 12:03:17 -07:00

81 lines
2.2 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.
*
* @format
* @flow
*/
import ElementBox from './ElementBox';
import * as React from 'react';
const {useEffect, useState} = React;
const hook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
export default function DevtoolsHighlighter(): React.Node {
const [inspected, setInspected] = useState(null);
useEffect(() => {
let devToolsAgent = null;
let hideTimeoutId = null;
function onAgentHideNativeHighlight() {
// we wait to actually hide in order to avoid flicker
clearTimeout(hideTimeoutId);
hideTimeoutId = setTimeout(() => {
setInspected(null);
}, 100);
}
function onAgentShowNativeHighlight(node: any) {
clearTimeout(hideTimeoutId);
// Shape of `node` is different in Fabric.
const component = node.canonical ?? node;
component.measure((x, y, width, height, left, top) => {
setInspected({
frame: {left, top, width, height},
});
});
}
function cleanup() {
const currentAgent = devToolsAgent;
if (currentAgent != null) {
currentAgent.removeListener(
'hideNativeHighlight',
onAgentHideNativeHighlight,
);
currentAgent.removeListener(
'showNativeHighlight',
onAgentShowNativeHighlight,
);
currentAgent.removeListener('shutdown', cleanup);
devToolsAgent = null;
}
}
function _attachToDevtools(agent: Object) {
devToolsAgent = agent;
agent.addListener('hideNativeHighlight', onAgentHideNativeHighlight);
agent.addListener('showNativeHighlight', onAgentShowNativeHighlight);
agent.addListener('shutdown', cleanup);
}
hook.on('react-devtools', _attachToDevtools);
if (hook.reactDevtoolsAgent) {
_attachToDevtools(hook.reactDevtoolsAgent);
}
return () => {
hook.off('react-devtools', _attachToDevtools);
cleanup();
};
}, []);
if (inspected != null) {
return <ElementBox frame={inspected.frame} />;
}
return null;
}