Changed highlight-on-search behavior to use TreeContext
Brian Vaughn committed
Apr 12, 2019 at 18:14 UTC
ca7eb3c8293665fbff1b1f1fb49778dbb861efef
3 files changed
+37
-50
src/devtools/views/Components/Element.js
+2
-2
@@ -44,7 +44,7 @@ export default function ElementView({ data, index, style }: Props) {
44
const {
45
lastScrolledIDRef,
46
treeFocused,
47
- isUsingKeyboardOrSearch,
47
+ isNavigatingWithKeyboard,
48
onElementMouseEnter,
49
} = data;
50
const id = element === null ? null : element.id;
@@ -122,7 +122,7 @@ export default function ElementView({ data, index, style }: Props) {
122
className = treeFocused
123
? styles.SelectedElement
124
: styles.InactiveSelectedElement;
125
- } else if (isHovered && !isUsingKeyboardOrSearch) {
125
+ } else if (isHovered && !isNavigatingWithKeyboard) {
126
className = styles.HoveredElement;
127
}
128
src/devtools/views/Components/SearchInput.js
+8
-27
@@ -8,12 +8,9 @@ import Icon from '../Icon';
8
9
import styles from './SearchInput.css';
10
11
-type Props = {|
12
- onSearchInteraction: () => void,
13
-|};
11
+type Props = {||};
12
13
export default function SearchInput(props: Props) {
16
- const { onSearchInteraction } = props;
14
const {
15
goToNextSearchResult,
16
goToPreviousSearchResult,
@@ -28,17 +25,10 @@ export default function SearchInput(props: Props) {
25
const inputRef = useRef<HTMLInputElement | null>(null);
26
27
const handleTextChange = useCallback(
31
- ({ currentTarget }) => {
32
- setSearchText(currentTarget.value);
33
- onSearchInteraction();
34
- },
35
- [setSearchText, onSearchInteraction]
28
+ ({ currentTarget }) => setSearchText(currentTarget.value),
29
+ [setSearchText]
30
);
37
-
38
- const resetSearch = useCallback(() => {
39
- setSearchText('');
40
- onSearchInteraction();
41
- }, [setSearchText, onSearchInteraction]);
31
+ const resetSearch = useCallback(() => setSearchText(''), [setSearchText]);
32
33
const handleKeyDown = useCallback(
34
event => {
@@ -46,29 +36,26 @@ export default function SearchInput(props: Props) {
36
switch (event.key) {
37
case 'ArrowDown':
38
selectNextElementInTree();
49
- onSearchInteraction();
39
event.preventDefault();
40
break;
41
case 'ArrowUp':
42
selectPreviousElementInTree();
54
- onSearchInteraction();
43
event.preventDefault();
44
break;
45
default:
46
break;
47
}
48
},
61
- [selectNextElementInTree, selectPreviousElementInTree, onSearchInteraction]
49
+ [selectNextElementInTree, selectPreviousElementInTree]
50
);
51
52
const handleInputKeyPress = useCallback(
53
({ key }) => {
54
if (key === 'Enter') {
55
goToNextSearchResult();
68
- onSearchInteraction();
56
}
57
},
71
- [goToNextSearchResult, onSearchInteraction]
58
+ [goToNextSearchResult]
59
);
60
61
// Auto-focus search input
@@ -119,10 +106,7 @@ export default function SearchInput(props: Props) {
106
<Button
107
className={styles.IconButton}
108
disabled={!searchText}
122
- onClick={() => {
123
- goToPreviousSearchResult();
124
- onSearchInteraction();
125
- }}
109
+ onClick={goToPreviousSearchResult}
110
title="Scroll to previous search result"
111
>
112
<ButtonIcon type="up" />
@@ -130,10 +114,7 @@ export default function SearchInput(props: Props) {
114
<Button
115
className={styles.IconButton}
116
disabled={!searchText}
133
- onClick={() => {
134
- goToNextSearchResult();
135
- onSearchInteraction();
136
- }}
117
+ onClick={goToNextSearchResult}
118
title="Scroll to next search result"
119
>
120
<ButtonIcon type="down" />
src/devtools/views/Components/Tree.js
+27
-21
@@ -27,7 +27,7 @@ export type ItemData = {|
27
baseDepth: number,
28
numElements: number,
29
getElementAtIndex: (index: number) => Element | null,
30
- isUsingKeyboardOrSearch: boolean,
30
+ isNavigatingWithKeyboard: boolean,
31
lastScrolledIDRef: { current: number | null },
32
onElementMouseEnter: (id: number) => void,
33
treeFocused: boolean,
@@ -41,6 +41,8 @@ export default function Tree(props: Props) {
41
getElementAtIndex,
42
numElements,
43
ownerStack,
44
+ searchIndex,
45
+ searchResults,
46
selectedElementID,
47
selectedElementIndex,
48
selectChildElementInTree,
@@ -52,7 +54,9 @@ export default function Tree(props: Props) {
54
} = useContext(TreeContext);
55
const bridge = useContext(BridgeContext);
56
const store = useContext(StoreContext);
55
- const [isUsingKeyboardOrSearch, setIsUsingKeyboardOrSearch] = useState(false);
57
+ const [isNavigatingWithKeyboard, setIsNavigatingWithKeyboard] = useState(
58
+ false
59
+ );
60
// $FlowFixMe https://github.com/facebook/flow/issues/7341
61
const listRef = useRef<FixedSizeList<ItemData> | null>(null);
62
const treeRef = useRef<HTMLDivElement | null>(null);
@@ -144,7 +148,7 @@ export default function Tree(props: Props) {
148
default:
149
return;
150
}
147
- setIsUsingKeyboardOrSearch(true);
151
+ setIsNavigatingWithKeyboard(true);
152
};
153
154
// It's important to listen to the ownerDocument to support the browser extension.
@@ -210,8 +214,18 @@ export default function Tree(props: Props) {
214
215
// If we switch the selected element while using the keyboard,
216
// start highlighting it in the DOM instead of the last hovered node.
217
+ const searchRef = useRef({ searchIndex, searchResults });
218
useEffect(() => {
214
- if (isUsingKeyboardOrSearch) {
219
+ let didSelectNewSearchResult = false;
220
+ if (
221
+ searchRef.current.searchIndex !== searchIndex ||
222
+ searchRef.current.searchResults !== searchResults
223
+ ) {
224
+ searchRef.current.searchIndex = searchIndex;
225
+ searchRef.current.searchResults = searchResults;
226
+ didSelectNewSearchResult = true;
227
+ }
228
+ if (isNavigatingWithKeyboard || didSelectNewSearchResult) {
229
if (selectedElementID !== null) {
230
highlightElementInDOM(selectedElementID);
231
} else {
@@ -220,8 +234,10 @@ export default function Tree(props: Props) {
234
}
235
}, [
236
bridge,
223
- isUsingKeyboardOrSearch,
237
+ isNavigatingWithKeyboard,
238
highlightElementInDOM,
239
+ searchIndex,
240
+ searchResults,
241
selectedElementID,
242
]);
243
@@ -230,29 +246,23 @@ export default function Tree(props: Props) {
246
id => {
247
// Ignore hover while we're navigating with keyboard.
248
// This avoids flicker from the hovered nodes under the mouse.
233
- if (!isUsingKeyboardOrSearch) {
249
+ if (!isNavigatingWithKeyboard) {
250
highlightElementInDOM(id);
251
}
252
},
237
- [isUsingKeyboardOrSearch, highlightElementInDOM]
253
+ [isNavigatingWithKeyboard, highlightElementInDOM]
254
);
255
256
const handleMouseMove = useCallback(() => {
257
// We started using the mouse again.
258
// This will enable hover styles in individual rows.
243
- setIsUsingKeyboardOrSearch(false);
259
+ setIsNavigatingWithKeyboard(false);
260
}, []);
261
262
const handleMouseLeave = useCallback(() => {
263
bridge.send('clearHighlightedElementInDOM');
264
}, [bridge]);
265
250
- const handleSearchInteraction = useCallback(() => {
251
- // We started navigating using search.
252
- // This will disable hover styles and start highlighting DOM elements.
253
- setIsUsingKeyboardOrSearch(true);
254
- }, []);
255
-
266
// Let react-window know to re-render any time the underlying tree data changes.
267
// This includes the owner context, since it controls a filtered view of the tree.
268
const itemData = useMemo<ItemData>(
@@ -260,7 +270,7 @@ export default function Tree(props: Props) {
270
baseDepth,
271
numElements,
272
getElementAtIndex,
263
- isUsingKeyboardOrSearch,
273
+ isNavigatingWithKeyboard,
274
onElementMouseEnter: handleElementMouseEnter,
275
lastScrolledIDRef,
276
treeFocused,
@@ -269,7 +279,7 @@ export default function Tree(props: Props) {
279
baseDepth,
280
numElements,
281
getElementAtIndex,
272
- isUsingKeyboardOrSearch,
282
+ isNavigatingWithKeyboard,
283
handleElementMouseEnter,
284
lastScrolledIDRef,
285
treeFocused,
@@ -279,11 +289,7 @@ export default function Tree(props: Props) {
289
return (
290
<div className={styles.Tree} ref={treeRef}>
291
<div className={styles.SearchInput}>
282
- {ownerStack.length > 0 ? (
283
- <OwnersStack />
284
- ) : (
285
- <SearchInput onSearchInteraction={handleSearchInteraction} />
286
- )}
292
+ {ownerStack.length > 0 ? <OwnersStack /> : <SearchInput />}
293
<InspectHostNodesToggle />
294
</div>
295
<div