@samitouri / QOS-React / commits / 1c57ca0a1c

Use focus state from elements tree instead of ownerDocument

Lucas Cordeiro committed Apr 9, 2019 at 18:58 UTC 1c57ca0a1c00705a679e26bc6950d2bf28ec9e82
2 files changed +38 -31
src/devtools/views/Components/Element.js
+2 -29
@@ -2,10 +2,8 @@
2
3 import React, {
4 Fragment,
5 - useState,
5 useCallback,
6 useContext,
8 - useEffect,
7 useLayoutEffect,
8 useMemo,
9 useRef,
@@ -37,13 +35,12 @@ export default function ElementView({ data, index, style }: Props) {
35 const bridge = useContext(BridgeContext);
36 const store = useContext(StoreContext);
37
40 - const [windowFocused, setWindowFocused] = useState<boolean>(true);
41 -
38 const element = getElementAtIndex(index);
39
40 const id = element === null ? null : element.id;
41 const isSelected = selectedElementID === id;
42 const lastScrolledIDRef = data.lastScrolledIDRef;
43 + const treeFocused = data.treeFocused;
44
45 const handleDoubleClick = useCallback(() => {
46 if (id !== null) {
@@ -53,30 +50,6 @@ export default function ElementView({ data, index, style }: Props) {
50
51 const ref = useRef<HTMLSpanElement | null>(null);
52
56 - useEffect(() => {
57 - if (ref.current === null || !isSelected) {
58 - return () => {};
59 - }
60 -
61 - const handleFocus = () => {
62 - setWindowFocused(true);
63 - };
64 -
65 - const handleBlur = () => {
66 - setWindowFocused(false);
67 - };
68 -
69 - const ownerDocument = ref.current.ownerDocument.defaultView;
70 -
71 - ownerDocument.addEventListener('focus', handleFocus);
72 - ownerDocument.addEventListener('blur', handleBlur);
73 -
74 - return () => {
75 - ownerDocument.removeEventListener('focus', handleFocus);
76 - ownerDocument.removeEventListener('blur', handleBlur);
77 - };
78 - }, [isSelected]);
79 -
53 // The tree above has its own autoscrolling, but it only works for rows.
54 // However, even when the row gets into the viewport, the component name
55 // might be too far left or right on the screen. Adjust it in this case.
@@ -147,7 +120,7 @@ export default function ElementView({ data, index, style }: Props) {
120 return (
121 <div
122 className={
150 - isSelected && windowFocused
123 + isSelected && treeFocused
124 ? styles.SelectedElement
125 : isSelected
126 ? styles.InactiveElement
src/devtools/views/Components/Tree.js
+36 -2
@@ -1,6 +1,7 @@
1 // @flow
2
3 import React, {
4 + useState,
5 useCallback,
6 useContext,
7 useEffect,
@@ -27,6 +28,7 @@ export type ItemData = {|
28 numElements: number,
29 getElementAtIndex: (index: number) => Element | null,
30 lastScrolledIDRef: { current: number | null },
31 + treeFocused: boolean,
32 |};
33
34 type Props = {||};
@@ -46,6 +48,9 @@ export default function Tree(props: Props) {
48 // $FlowFixMe https://github.com/facebook/flow/issues/7341
49 const listRef = useRef<FixedSizeList<ItemData> | null>(null);
50 const treeRef = useRef<HTMLDivElement | null>(null);
51 + const elementsRef = useRef<HTMLDivElement | null>(null);
52 +
53 + const [treeFocused, setTreeFocused] = useState<boolean>(false);
54
55 const { lineHeight } = useContext(SettingsContext);
56
@@ -112,6 +117,30 @@ export default function Tree(props: Props) {
117 selectPreviousElementInTree,
118 ]);
119
120 + useEffect(() => {
121 + if (elementsRef.current === null) {
122 + return () => {};
123 + }
124 +
125 + const handleFocusIn = () => {
126 + setTreeFocused(true);
127 + };
128 +
129 + const handleFocusOut = () => {
130 + setTreeFocused(false);
131 + };
132 +
133 + const elementsElement = elementsRef.current;
134 +
135 + elementsElement.addEventListener('focusin', handleFocusIn);
136 + elementsElement.addEventListener('focusout', handleFocusOut);
137 +
138 + return () => {
139 + elementsElement.removeEventListener('focusin', handleFocusIn);
140 + elementsElement.removeEventListener('focusout', handleFocusOut);
141 + };
142 + }, []);
143 +
144 // Let react-window know to re-render any time the underlying tree data changes.
145 // This includes the owner context, since it controls a filtered view of the tree.
146 const itemData = useMemo<ItemData>(
@@ -120,8 +149,9 @@ export default function Tree(props: Props) {
149 numElements,
150 getElementAtIndex,
151 lastScrolledIDRef,
152 + treeFocused,
153 }),
124 - [baseDepth, numElements, getElementAtIndex, lastScrolledIDRef]
154 + [baseDepth, numElements, getElementAtIndex, lastScrolledIDRef, treeFocused]
155 );
156
157 const handleMouseLeave = useCallback(() => {
@@ -134,7 +164,11 @@ export default function Tree(props: Props) {
164 {ownerStack.length > 0 ? <OwnersStack /> : <SearchInput />}
165 <InspectHostNodesToggle />
166 </div>
137 - <div className={styles.AutoSizerWrapper} onMouseLeave={handleMouseLeave}>
167 + <div
168 + className={styles.AutoSizerWrapper}
169 + onMouseLeave={handleMouseLeave}
170 + ref={elementsRef}
171 + >
172 <AutoSizer>
173 {({ height, width }) => (
174 // $FlowFixMe https://github.com/facebook/flow/issues/7341