import type {ReactContext} from 'shared/ReactTypes';
import * as React from 'react';
import {createContext, useContext, useEffect, useState} from 'react';
import {
BridgeContext,
StoreContext,
} from 'react-devtools-shared/src/devtools/views/context';
import {TreeStateContext} from 'react-devtools-shared/src/devtools/views/Components/TreeContext';
import type {StateContext} from 'react-devtools-shared/src/devtools/views/Components/TreeContext';
import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
import type Store from 'react-devtools-shared/src/devtools/store';
import type {StyleAndLayout as StyleAndLayoutBackend} from 'react-devtools-shared/src/backend/NativeStyleEditor/types';
import type {StyleAndLayout as StyleAndLayoutFrontend} from './types';
type Context = StyleAndLayoutFrontend | null;
const NativeStyleContext: ReactContext<Context> = createContext<Context>(
((null: any): Context),
);
NativeStyleContext.displayName = 'NativeStyleContext';
type Props = {
children: React$Node,
};
function NativeStyleContextController({children}: Props): React.Node {
const bridge = useContext<FrontendBridge>(BridgeContext);
const store = useContext<Store>(StoreContext);
const {inspectedElementID} = useContext<StateContext>(TreeStateContext);
const [currentStyleAndLayout, setCurrentStyleAndLayout] =
useState<StyleAndLayoutFrontend | null>(null);
useEffect(() => {
if (inspectedElementID === null) {
setCurrentStyleAndLayout(null);
return () => {};
}
let requestTimeoutId: TimeoutID | null = null;
const sendRequest = () => {
requestTimeoutId = null;
const rendererID = store.getRendererIDForElement(inspectedElementID);
if (rendererID !== null) {
bridge.send('NativeStyleEditor_measure', {
id: inspectedElementID,
rendererID,
});
}
};
sendRequest();
const onStyleAndLayout = ({id, layout, style}: StyleAndLayoutBackend) => {
if (id === inspectedElementID) {
if (requestTimeoutId !== null) {
clearTimeout(requestTimeoutId);
}
requestTimeoutId = setTimeout(sendRequest, 1000);
}
const styleAndLayout: StyleAndLayoutFrontend = {
layout,
style,
};
setCurrentStyleAndLayout(styleAndLayout);
};
bridge.addListener('NativeStyleEditor_styleAndLayout', onStyleAndLayout);
return () => {
bridge.removeListener(
'NativeStyleEditor_styleAndLayout',
onStyleAndLayout,
);
if (requestTimeoutId !== null) {
clearTimeout(requestTimeoutId);
}
};
}, [bridge, inspectedElementID, store]);
return (
<NativeStyleContext.Provider value={currentStyleAndLayout}>
{children}
</NativeStyleContext.Provider>
);
}
export {NativeStyleContext, NativeStyleContextController};