@samitouri / QOS-React-2 / commits / 72eccb465d

Make DOM selection binding one-way

Dan committed Apr 9, 2019 at 01:30 UTC 72eccb465d7f7b4659d002e2a8510423546f0928
2 files changed +25 -47
shells/browser/shared/src/main.js
+20 -33
@@ -85,12 +85,6 @@ function createPanelIfReactLoaded() {
85 );
86 });
87
88 - // Remember if we should sync the browser DevTools to the React tab.
89 - // We'll only do that if user intentionally chooses a different React component.
90 - bridge.addListener('selectElement', () => {
91 - hasReactSelectionChanged = true;
92 - });
93 -
88 // This flag lets us tip the Store off early that we expect to be profiling.
89 // This avoids flashing a temporary "Profiling not supported" message in the Profiler tab,
90 // after a user has clicked the "reload and profile" button.
@@ -168,51 +162,39 @@ function createPanelIfReactLoaded() {
162 container._hasInitialHTMLBeenCleared = true;
163 }
164
171 - function maybeSetReactSelectionFromBrowser() {
165 + function setReactSelectionFromBrowser() {
166 // When the user chooses a different node in the browser Elements tab,
167 // copy it over to the hook object so that we can sync the selection.
168 chrome.devtools.inspectedWindow.eval(
175 - // Don't reset selection if it didn't change in Elements tab.
176 - '(window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0 !== $0)' +
177 - ' ? (window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0 = $0, true)' +
178 - ' : false',
179 - (didChangeSelection, error) => {
169 + '(window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0 = $0, undefined)',
170 + (_, error) => {
171 if (error) {
172 console.error(error);
182 - } else if (didChangeSelection) {
173 + } else {
174 bridge.send('syncSelectionFromNativeElementsPanel');
175 }
176 }
177 );
178 }
179
189 - let hasReactSelectionChanged = false;
190 -
191 - function maybeSetBrowserSelectionFromReact() {
192 - // Don't change the browser element selection when navigating away
193 - // from the Components tab if the user didn't change the React selection.
194 - if (!hasReactSelectionChanged) {
180 + // When the user selects another item in the native Elements tab,
181 + // select the corresponding React component.
182 + let isListeningToNativeSelectionChange = false;
183 + function ensureListeningToNativeSelectionChange() {
184 + if (isListeningToNativeSelectionChange) {
185 return;
186 }
197 - hasReactSelectionChanged = false;
198 - chrome.devtools.inspectedWindow.eval(
199 - '(window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0 != null)' +
200 - ' ? (inspect(window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0), true)' +
201 - ' : false',
202 - (_, error) => {
203 - if (error) {
204 - console.error(error);
205 - }
206 - }
207 - );
187 + isListeningToNativeSelectionChange = true;
188 + setReactSelectionFromBrowser();
189 + chrome.devtools.panels.elements.onSelectionChanged.addListener(() => {
190 + setReactSelectionFromBrowser();
191 + });
192 }
193
194 let currentPanel = null;
195
196 chrome.devtools.panels.create('⚛ Components', '', 'panel.html', panel => {
197 panel.onShown.addListener(panel => {
214 - maybeSetReactSelectionFromBrowser();
215 -
198 if (currentPanel === panel) {
199 return;
200 }
@@ -225,9 +207,14 @@ function createPanelIfReactLoaded() {
207 render('components');
208 panel.injectStyles(cloneStyleTags);
209 }
210 +
211 + // Don't start listening to native selection change
212 + // until *after* the panel is visible. Otherwise, we'll
213 + // set the selected element too early and won't scroll
214 + // to it the first time we open Components panel.
215 + ensureListeningToNativeSelectionChange();
216 });
217 panel.onHidden.addListener(() => {
230 - maybeSetBrowserSelectionFromReact();
218 // TODO: Stop highlighting and stuff.
219 });
220 });
src/backend/agent.js
+5 -14
@@ -308,22 +308,13 @@ export default class Agent extends EventEmitter {
308 if (renderer == null) {
309 console.warn(`Invalid renderer id "${rendererID}" for element "${id}"`);
310 } else {
311 - // When a different React component is selected, we want to store
312 - // the active DOM node ($0) on the global hook so that content script
313 - // can update the native elements panel to match it.
314 - const node = ((renderer.findNativeByFiberID(id): any): HTMLElement);
315 - if (node !== null) {
316 - // However, we don't want to do it if the current $0 node already
317 - // belongs to this component. In this case we were probably inspecting
318 - // a part of its host subtree, and changing $0 would be disuptive.
319 - const prev$0 = window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0;
320 - const prev$0ID = this.getIDForNode(prev$0);
321 - if (prev$0ID !== id) {
322 - window.__REACT_DEVTOOLS_GLOBAL_HOOK__.$0 = node;
323 - }
324 - }
311 renderer.selectElement(id);
312 this._bridge.send('selectElement');
313 + // TODO: If there was a way to change the selected DOM element
314 + // in native Elements tab without forcing a switch to it, we'd do it here.
315 + // For now, it doesn't seem like there is a way to do that:
316 + // https://github.com/bvaughn/react-devtools-experimental/issues/102
317 + // (Setting $0 doesn't work, and calling inspect() switches the tab.)
318 }
319 };
320