Make screen dimension reflection fast

Summary:
After loading a layout plugin snapshot, I noticed the plugin feels really sluggish. I noticed that getDimensions, which recursively walks the full tree, is triggered on every rendering, although the state it introduces is only required when opening a screenshot visualizer. So Moved the function invocation to there.

Also did some first steps on supporting iOS; the visualizer will no show a preview of iOS as well. I'll leave implementing the highlights to a volunteer :)

Reviewed By: passy

Differential Revision: D29262697

fbshipit-source-id: b13b19b013eeeb98abb66fb648a193c69688a7e3
This commit is contained in:
Michel Weststrate
2021-06-22 04:09:36 -07:00
committed by Facebook GitHub Bot
parent c6a7d48864
commit b9250e7795

View File

@@ -35,6 +35,7 @@ import {
IDEFileResolver, IDEFileResolver,
IDEType, IDEType,
} from 'flipper'; } from 'flipper';
import {message} from 'antd';
type State = { type State = {
init: boolean; init: boolean;
@@ -335,8 +336,9 @@ export default class LayoutPlugin extends FlipperPlugin<
if (this.state.visualizerWindow) { if (this.state.visualizerWindow) {
this.state.visualizerWindow.close(); this.state.visualizerWindow.close();
} else { } else {
const screenDimensions = this.state.screenDimensions; const screenDimensions = this.loadScreenDimensions();
if (!screenDimensions) { if (!screenDimensions || !this.state.visualizerScreenshot) {
message.warn('No visualizer screenshot or dimensions available');
return; return;
} }
const visualizerWindow = window.open( const visualizerWindow = window.open(
@@ -376,44 +378,39 @@ export default class LayoutPlugin extends FlipperPlugin<
}); });
}; };
getScreenDimensions(): {width: number; height: number} | null { loadScreenDimensions(): {width: number; height: number} | null {
if (this.state.screenDimensions) { // Walk the layout tree from root node down until a node with width and height is found.
return this.state.screenDimensions; // Assume these are the dimensions of the screen.
} let elementId = this.props.persistedState.rootElement;
while (elementId != null) {
requestIdleCallback(() => { const element: any = this.props.persistedState.elements[elementId];
// Walk the layout tree from root node down until a node with width and height is found. if (!element) {
// Assume these are the dimensions of the screen.
let elementId = this.props.persistedState.rootElement;
while (elementId != null) {
const element = this.props.persistedState.elements[elementId];
if (!element) {
return null;
}
if (element.data.View?.width) {
break;
}
elementId = element.children[0];
}
if (elementId == null) {
return null; return null;
} }
const element = this.props.persistedState.elements[elementId];
if ( if (
element == null || element.data?.View?.width ||
typeof element.data.View?.width != 'object' || element.data?.UIView?.bounds?.size?.width
typeof element.data.View?.height != 'object'
) { ) {
return null; break;
} }
const screenDimensions = { elementId = element.children[0];
width: element.data.View?.width.value, }
height: element.data.View?.height.value, if (elementId == null) {
}; return null;
this.setState({screenDimensions}); }
}); const element: any = this.props.persistedState.elements[elementId];
const width =
return null; element?.data?.View?.width?.value ??
element?.data?.UIView?.bounds?.size?.width;
const height =
element?.data?.View?.height?.value ??
element?.data?.UIView?.bounds?.size?.height;
if (typeof width !== 'number' || typeof height !== 'number') {
return null;
}
const screenDimensions = {width, height};
this.setState({screenDimensions});
return screenDimensions;
} }
render() { render() {
@@ -456,8 +453,6 @@ export default class LayoutPlugin extends FlipperPlugin<
const showAnalyzeYogaPerformanceButton = GK.get('flipper_yogaperformance'); const showAnalyzeYogaPerformanceButton = GK.get('flipper_yogaperformance');
const screenDimensions = this.getScreenDimensions();
if (!this.state.init) { if (!this.state.init) {
return null; return null;
} }
@@ -543,14 +538,14 @@ export default class LayoutPlugin extends FlipperPlugin<
) : null} ) : null}
</DetailSidebar> </DetailSidebar>
{this.state.visualizerWindow && {this.state.visualizerWindow &&
screenDimensions && this.state.screenDimensions &&
(this.state.visualizerScreenshot ? ( (this.state.visualizerScreenshot ? (
<VisualizerPortal <VisualizerPortal
container={this.state.visualizerWindow.document.body} container={this.state.visualizerWindow.document.body}
elements={this.props.persistedState.elements} elements={this.props.persistedState.elements}
highlightedElement={this.state.highlightedElement} highlightedElement={this.state.highlightedElement}
screenshotURL={this.state.visualizerScreenshot} screenshotURL={this.state.visualizerScreenshot}
screenDimensions={screenDimensions} screenDimensions={this.state.screenDimensions}
/> />
) : ( ) : (
'Loading...' 'Loading...'