-
Notifications
You must be signed in to change notification settings - Fork 51k
Expand file tree
/
Copy pathcontext.js
More file actions
105 lines (87 loc) · 3.28 KB
/
context.js
File metadata and controls
105 lines (87 loc) · 3.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/**
* 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
*/
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);
// This effect handler polls for updates on the currently selected element.
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,
});
}
};
// Send the initial measurement request.
// We'll poll for an update in the response handler below.
sendRequest();
const onStyleAndLayout = ({id, layout, style}: StyleAndLayoutBackend) => {
// If this is the element we requested, wait a little bit and then ask for another update.
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};