diff --git a/src/fb-stubs/LayoutInspectorSidebarExtensions.tsx b/src/fb-stubs/LayoutInspectorSidebarExtensions.tsx index 1bbba7a49..0107af64d 100644 --- a/src/fb-stubs/LayoutInspectorSidebarExtensions.tsx +++ b/src/fb-stubs/LayoutInspectorSidebarExtensions.tsx @@ -4,4 +4,15 @@ * LICENSE file in the root directory of this source tree. * @format */ -export default []; + +import {PluginClient, Client, ElementID} from 'flipper'; +import {Logger} from 'src/fb-interfaces/Logger'; + +export default [] as Array< + ( + client: PluginClient, + realClient: Client, + selectedNode: ElementID, + logger: Logger, + ) => React.ReactNode +>; diff --git a/src/plugins/layout/Inspector.js b/src/plugins/layout/Inspector.tsx similarity index 74% rename from src/plugins/layout/Inspector.js rename to src/plugins/layout/Inspector.tsx index 7947c2d86..1bcb5c3b0 100644 --- a/src/plugins/layout/Inspector.js +++ b/src/plugins/layout/Inspector.tsx @@ -5,36 +5,36 @@ * @format */ -import type { +import { ElementID, Element, PluginClient, + ElementsInspector, ElementSearchResultSet, } from 'flipper'; -import {ElementsInspector} from 'flipper'; import {Component} from 'react'; import debounce from 'lodash.debounce'; - -import type {PersistedState, ElementMap} from './'; +import {PersistedState, ElementMap} from './'; +import React from 'react'; type GetNodesOptions = { - force?: boolean, - ax?: boolean, - forAccessibilityEvent?: boolean, + force?: boolean; + ax?: boolean; + forAccessibilityEvent?: boolean; }; type Props = { - ax?: boolean, - client: PluginClient, - showsSidebar: boolean, - inAlignmentMode?: boolean, - selectedElement: ?ElementID, - selectedAXElement: ?ElementID, - onSelect: (ids: ?ElementID) => void, - onDataValueChanged: (path: Array, value: any) => void, - setPersistedState: (state: $Shape) => void, - persistedState: PersistedState, - searchResults: ?ElementSearchResultSet, + ax?: boolean; + client: PluginClient; + showsSidebar: boolean; + inAlignmentMode?: boolean; + selectedElement: ElementID | null | undefined; + selectedAXElement: ElementID | null | undefined; + onSelect: (ids: ElementID | null | undefined) => void; + onDataValueChanged: (path: Array, value: any) => void; + setPersistedState: (state: Partial) => void; + persistedState: PersistedState; + searchResults: ElementSearchResultSet | null; }; export default class Inspector extends Component { @@ -76,8 +76,12 @@ export default class Inspector extends Component { const elements: Array = Object.values( this.props.persistedState.AXelements, ); - return elements.find(i => i?.data?.Accessibility?.['accessibility-focused']) - ?.id; + const focusedElement = elements.find(i => + Boolean( + i.data.Accessibility && i.data.Accessibility['accessibility-focused'], + ), + ); + return focusedElement ? focusedElement.id : null; }; getAXContextMenuExtensions = () => @@ -106,7 +110,7 @@ export default class Inspector extends Component { ({ nodes, }: { - nodes: Array<{id: ElementID, children: Array}>, + nodes: Array<{id: ElementID; children: Array}>; }) => { const ids = nodes .map(n => [n.id, ...(n.children || [])]) @@ -154,7 +158,11 @@ export default class Inspector extends Component { selectedElement ]; if (newlySelectedElem) { - this.props.onSelect(newlySelectedElem.extraInfo?.linkedNode); + this.props.onSelect( + newlySelectedElem.extraInfo + ? newlySelectedElem.extraInfo.linkedNode + : null, + ); } } else if ( !ax && @@ -166,7 +174,11 @@ export default class Inspector extends Component { selectedAXElement ]; if (newlySelectedAXElem) { - this.props.onSelect(newlySelectedAXElem.extraInfo?.linkedNode); + this.props.onSelect( + newlySelectedAXElem.extraInfo + ? newlySelectedAXElem.extraInfo.linkedNode + : null, + ); } } } @@ -179,11 +191,13 @@ export default class Inspector extends Component { (acc: ElementMap, element: Element) => { acc[element.id] = { ...element, - expanded: this.elements()[element.id]?.expanded, + expanded: this.elements()[element.id] + ? this.elements()[element.id].expanded + : false, }; return acc; }, - new Map(), + {}, ); this.props.setPersistedState({ [this.props.ax ? 'AXelements' : 'elements']: { @@ -193,17 +207,19 @@ export default class Inspector extends Component { }); } - invalidate(ids: Array): Promise> { + async invalidate(ids: Array): Promise> { if (ids.length === 0) { return Promise.resolve([]); } - return this.getNodes(ids, {}).then((elements: Array) => { - const children = elements - .filter((element: Element) => this.elements()[element.id]?.expanded) - .map((element: Element) => element.children) - .reduce((acc, val) => acc.concat(val), []); - return this.invalidate(children); - }); + const elements = await this.getNodes(ids, {}); + const children = elements + .filter( + (element: Element) => + this.elements()[element.id] && this.elements()[element.id].expanded, + ) + .map((element: Element) => element.children) + .reduce((acc, val) => acc.concat(val), []); + return this.invalidate(children); } updateElement(id: ElementID, data: Object) { @@ -225,7 +241,7 @@ export default class Inspector extends Component { // element has no children so we're as deep as we can be return; } - return this.getChildren(element.id, {}).then((elements: Array) => { + return this.getChildren(element.id, {}).then(() => { if (element.children.length >= 2) { // element has two or more children so we can stop expanding return; @@ -245,32 +261,32 @@ export default class Inspector extends Component { return this.getNodes(this.elements()[id].children, options); } - getNodes( + async getNodes( ids: Array = [], options: GetNodesOptions, ): Promise> { - const {forAccessibilityEvent} = options; - if (ids.length > 0) { - return this.props.client - .call(this.call().GET_NODES, { + const {forAccessibilityEvent} = options; + const { + elements, + }: {elements: Array} = await this.props.client.call( + this.call().GET_NODES, + { ids, forAccessibilityEvent, selected: false, - }) - .then(({elements}) => { - elements.forEach(e => this.updateElement(e.id, e)); - return elements; - }); + }, + ); + elements.forEach(e => this.updateElement(e.id, e)); + return elements; } else { - return Promise.resolve([]); + return []; } } - getAndExpandPath(path: Array) { - return Promise.all(path.map(id => this.getChildren(id, {}))).then(() => { - this.onElementSelected(path[path.length - 1]); - }); + async getAndExpandPath(path: Array) { + await Promise.all(path.map(id => this.getChildren(id, {}))); + this.onElementSelected(path[path.length - 1]); } onElementSelected = debounce((selectedKey: ElementID) => { @@ -278,7 +294,7 @@ export default class Inspector extends Component { this.props.onSelect(selectedKey); }); - onElementHovered = debounce((key: ?ElementID) => + onElementHovered = debounce((key: ElementID | null | undefined) => this.props.client.call(this.call().SET_HIGHLIGHTED, { id: key, isAlignmentMode: this.props.inAlignmentMode, diff --git a/src/plugins/layout/InspectorSidebar.js b/src/plugins/layout/InspectorSidebar.tsx similarity index 82% rename from src/plugins/layout/InspectorSidebar.js rename to src/plugins/layout/InspectorSidebar.tsx index 134e68a2d..2dcadfc32 100644 --- a/src/plugins/layout/InspectorSidebar.js +++ b/src/plugins/layout/InspectorSidebar.tsx @@ -5,22 +5,21 @@ * @format */ -import type {Element} from 'flipper'; -import type {PluginClient} from 'flipper'; -import type Client from '../../Client.tsx'; -import type {Logger} from '../../fb-interfaces/Logger.tsx'; - import { ManagedDataInspector, Panel, FlexCenter, styled, colors, + PluginClient, SidebarExtensions, + Element, } from 'flipper'; +import Client from '../../Client'; +import {Logger} from '../../fb-interfaces/Logger'; import {Component} from 'react'; - -const deepEqual = require('deep-equal'); +import deepEqual from 'deep-equal'; +import React from 'react'; const NoData = styled(FlexCenter)({ fontSize: 18, @@ -30,10 +29,10 @@ const NoData = styled(FlexCenter)({ type OnValueChanged = (path: Array, val: any) => void; type InspectorSidebarSectionProps = { - data: any, - id: string, - onValueChanged: ?OnValueChanged, - tooltips?: Object, + data: any; + id: string; + onValueChanged: OnValueChanged | null; + tooltips?: Object; }; class InspectorSidebarSection extends Component { @@ -51,7 +50,7 @@ class InspectorSidebarSection extends Component { ); } - extractValue = (val: any, depth: number) => { + extractValue = (val: any, _depth: number) => { if (val && val.__type__) { return { mutable: Boolean(val.__mutable__), @@ -84,14 +83,14 @@ class InspectorSidebarSection extends Component { } } -type Props = {| - element: ?Element, - tooltips?: Object, - onValueChanged: ?OnValueChanged, - client: PluginClient, - realClient: Client, - logger: Logger, -|}; +type Props = { + element: Element | null; + tooltips?: Object; + onValueChanged: OnValueChanged | null; + client: PluginClient; + realClient: Client; + logger: Logger; +}; export default class Sidebar extends Component { render() { @@ -115,12 +114,13 @@ export default class Sidebar extends Component { for (const key in element.data) { if (key === 'Extra Sections') { for (const extraSection in element.data[key]) { - let data = element.data[key][extraSection]; + const section = element.data[key][extraSection]; + let data = {}; // data might be sent as stringified JSON, we want to parse it for a nicer persentation. - if (typeof data === 'string') { + if (typeof section === 'string') { try { - data = JSON.parse(data); + data = JSON.parse(section); } catch (e) { // data was not a valid JSON, type is required to be an object console.error( @@ -128,6 +128,8 @@ export default class Sidebar extends Component { ); data = {}; } + } else { + data = section; } sections.push( { +): { + ROOT: 'rootAXElement' | 'rootElement'; + ELEMENTS: 'AXelements' | 'elements'; + ELEMENT: 'axElement' | 'element'; +} => { return { ROOT: AXMode ? 'rootAXElement' : 'rootElement', ELEMENTS: AXMode ? 'AXelements' : 'elements', @@ -25,14 +28,14 @@ function constructSearchResultTree( node: Element, isMatch: boolean, children: Array, - AXMode: boolean, - AXNode: ?Element, + _AXMode: boolean, + AXNode: Element | null, ): SearchResultTree { const searchResult = { id: node.id, isMatch, hasChildren: children.length > 0, - children: children.length > 0 ? children : null, + children: children.length > 0 ? children : [], element: node, axElement: AXNode, }; @@ -49,7 +52,7 @@ export function searchNodes( query: string, AXMode: boolean, state: PersistedState, -): ?SearchResultTree { +): SearchResultTree | null { // Even if the axMode is true, we will have to search the normal elements too. // The AXEelements will automatically populated in constructSearchResultTree const elements = state[propsForPersistedState(false).ELEMENTS]; @@ -83,20 +86,19 @@ class ProxyArchiveClient { this.persistedState = cloneDeep(persistedState); } persistedState: PersistedState; - subscribe(method: string, callback: (params: any) => void): void { + subscribe(_method: string, _callback: (params: any) => void): void { return; } - supportsMethod(method: string): Promise { + supportsMethod(_method: string): Promise { return Promise.resolve(false); } - send(method: string, params?: Object): void { + send(_method: string, _params?: Object): void { return; } - call(method: string, params?: Object): Promise { - const paramaters = params; + call(method: string, paramaters?: {[key: string]: any}): Promise { switch (method) { case 'getRoot': { const {rootElement} = this.persistedState; @@ -118,7 +120,7 @@ class ProxyArchiveClient { } const {ids} = paramaters; const arr: Array = []; - for (const id: ElementID of ids) { + for (const id of ids) { arr.push(this.persistedState.elements[id]); } return Promise.resolve({elements: arr}); @@ -129,7 +131,7 @@ class ProxyArchiveClient { } const {ids} = paramaters; const arr: Array = []; - for (const id: ElementID of ids) { + for (const id of ids) { arr.push(this.persistedState.AXelements[id]); } return Promise.resolve({elements: arr}); @@ -148,7 +150,7 @@ class ProxyArchiveClient { new Error('query is not passed as a params to getSearchResults'), ); } - let element = {}; + let element: Element; if (axEnabled) { if (!rootAXElement) { return Promise.reject(new Error('rootAXElement is undefined')); diff --git a/src/plugins/layout/Search.js b/src/plugins/layout/Search.tsx similarity index 81% rename from src/plugins/layout/Search.js rename to src/plugins/layout/Search.tsx index a70a5d2ab..e5f8f212f 100644 --- a/src/plugins/layout/Search.js +++ b/src/plugins/layout/Search.tsx @@ -5,10 +5,11 @@ * @format */ -import type {PluginClient, ElementSearchResultSet, Element} from 'flipper'; -import type {PersistedState, ElementMap} from './'; - +import {PersistedState, ElementMap} from './'; import { + PluginClient, + ElementSearchResultSet, + Element, SearchInput, SearchBox, SearchIcon, @@ -17,28 +18,29 @@ import { colors, } from 'flipper'; import {Component} from 'react'; +import React from 'react'; -export type SearchResultTree = {| - id: string, - isMatch: boolean, - hasChildren: boolean, - children: ?Array, - element: Element, - axElement: ?Element, // Not supported in iOS -|}; +export type SearchResultTree = { + id: string; + isMatch: boolean; + hasChildren: boolean; + children: Array; + element: Element; + axElement: Element | null; // Not supported in iOS +}; type Props = { - client: PluginClient, - inAXMode: boolean, - onSearchResults: (searchResults: ElementSearchResultSet) => void, - setPersistedState: (state: $Shape) => void, - persistedState: PersistedState, - initialQuery: ?string, + client: PluginClient; + inAXMode: boolean; + onSearchResults: (searchResults: ElementSearchResultSet) => void; + setPersistedState: (state: Partial) => void; + persistedState: PersistedState; + initialQuery: string | null; }; type State = { - value: string, - outstandingSearchQuery: ?string, + value: string; + outstandingSearchQuery: string | null; }; const LoadingSpinner = styled(LoadingIndicator)({ @@ -53,16 +55,18 @@ export default class Search extends Component { outstandingSearchQuery: null, }; - timer: TimeoutID; + timer: NodeJS.Timeout | undefined; - onChange = (e: SyntheticInputEvent<>) => { - clearTimeout(this.timer); + onChange = (e: React.ChangeEvent) => { + if (this.timer) { + clearTimeout(this.timer); + } const {value} = e.target; this.setState({value}); this.timer = setTimeout(() => this.performSearch(value), 200); }; - onKeyDown = (e: SyntheticKeyboardEvent<>) => { + onKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { this.performSearch(this.state.value); } @@ -73,7 +77,9 @@ export default class Search extends Component { const queryString = this.props.initialQuery ? this.props.initialQuery : ''; - clearTimeout(this.timer); + if (this.timer) { + clearTimeout(this.timer); + } this.timer = setTimeout(() => this.performSearch(queryString), 200); } } @@ -102,8 +108,8 @@ export default class Search extends Component { results, query, }: { - results: ?SearchResultTree, - query: string, + results: SearchResultTree | null; + query: string; }, axMode: boolean, ) { @@ -159,13 +165,14 @@ export default class Search extends Component { } getElementsFromSearchResultTree( - tree: ?SearchResultTree, + tree: SearchResultTree | null, ): Array { if (!tree) { return []; } let elements = [ { + children: [] as Array, id: tree.id, isMatch: tree.isMatch, hasChildren: Boolean(tree.children), diff --git a/src/plugins/layout/ToolbarIcon.js b/src/plugins/layout/ToolbarIcon.tsx similarity index 85% rename from src/plugins/layout/ToolbarIcon.js rename to src/plugins/layout/ToolbarIcon.tsx index 7a0295f4a..da2bbcf91 100644 --- a/src/plugins/layout/ToolbarIcon.js +++ b/src/plugins/layout/ToolbarIcon.tsx @@ -6,13 +6,14 @@ */ import {Glyph, styled, colors} from 'flipper'; +import React from 'react'; -type Props = {| - title: string, - icon: string, - active: boolean, - onClick: () => void, -|}; +type Props = { + title: string; + icon: string; + active: boolean; + onClick: () => void; +}; const ToolbarIcon = styled('div')({ marginRight: 9, diff --git a/src/plugins/layout/__tests__/ProxyArchiveClient.node.js b/src/plugins/layout/__tests__/ProxyArchiveClient.node.tsx similarity index 92% rename from src/plugins/layout/__tests__/ProxyArchiveClient.node.js rename to src/plugins/layout/__tests__/ProxyArchiveClient.node.tsx index 1cb48b36d..bc3863e6b 100644 --- a/src/plugins/layout/__tests__/ProxyArchiveClient.node.js +++ b/src/plugins/layout/__tests__/ProxyArchiveClient.node.tsx @@ -9,9 +9,9 @@ import { default as ProxyArchiveClient, searchNodes, } from '../ProxyArchiveClient'; -import type {PersistedState} from '../index'; -import type {ElementID, Element} from 'flipper'; -import type {SearchResultTree} from '../Search'; +import {PersistedState, ElementMap} from '../index'; +import {ElementID, Element} from 'flipper'; +import {SearchResultTree} from '../Search'; function constructElement( id: string, @@ -49,7 +49,7 @@ function constructPersistedState(axMode: boolean): PersistedState { let state = constructPersistedState(false); function populateChildren(state: PersistedState, axMode: boolean) { - const elements = {}; + const elements: ElementMap = {}; elements['root'] = constructElement('root', 'root view', [ 'child0', 'child1', @@ -95,7 +95,7 @@ beforeEach(() => { }); test('test the searchNode for root in axMode false', async () => { - const searchResult: ?SearchResultTree = await searchNodes( + const searchResult: SearchResultTree | null = await searchNodes( state.elements['root'], 'root', false, @@ -106,7 +106,7 @@ test('test the searchNode for root in axMode false', async () => { id: 'root', isMatch: true, hasChildren: false, - children: null, + children: [], element: state.elements['root'], axElement: null, }); @@ -115,7 +115,7 @@ test('test the searchNode for root in axMode false', async () => { test('test the searchNode for root in axMode true', async () => { state = constructPersistedState(true); populateChildren(state, true); - const searchResult: ?SearchResultTree = await searchNodes( + const searchResult: SearchResultTree | null = await searchNodes( state.AXelements['root'], 'RoOT', true, @@ -126,14 +126,14 @@ test('test the searchNode for root in axMode true', async () => { id: 'root', isMatch: true, hasChildren: false, - children: null, + children: [], element: state.AXelements['root'], // Even though AXElement exists, normal element will exist too axElement: state.AXelements['root'], }); }); test('test the searchNode which matches just one child', async () => { - const searchResult: ?SearchResultTree = await searchNodes( + const searchResult: SearchResultTree | null = await searchNodes( state.elements['root'], 'child0_child0', false, @@ -154,7 +154,7 @@ test('test the searchNode which matches just one child', async () => { id: 'child0_child0', isMatch: true, hasChildren: false, - children: null, + children: [], element: state.elements['child0_child0'], axElement: null, }, @@ -169,7 +169,7 @@ test('test the searchNode which matches just one child', async () => { }); test('test the searchNode for which matches multiple child', async () => { - const searchResult: ?SearchResultTree = await searchNodes( + const searchResult: SearchResultTree | null = await searchNodes( state.elements['root'], 'child0', false, @@ -190,7 +190,7 @@ test('test the searchNode for which matches multiple child', async () => { id: 'child0_child0', isMatch: true, hasChildren: false, - children: null, + children: [], element: state.elements['child0_child0'], axElement: null, }, @@ -198,7 +198,7 @@ test('test the searchNode for which matches multiple child', async () => { id: 'child0_child1', isMatch: true, hasChildren: false, - children: null, + children: [], element: state.elements['child0_child1'], axElement: null, }, @@ -215,7 +215,7 @@ test('test the searchNode for which matches multiple child', async () => { id: 'child1_child0', isMatch: true, hasChildren: false, - children: null, + children: [], element: state.elements['child1_child0'], axElement: null, }, @@ -231,7 +231,7 @@ test('test the searchNode for which matches multiple child', async () => { }); test('test the searchNode, it should not be case sensitive', async () => { - const searchResult: ?SearchResultTree = await searchNodes( + const searchResult: SearchResultTree | null = await searchNodes( state.elements['root'], 'ChIlD0', false, @@ -252,7 +252,7 @@ test('test the searchNode, it should not be case sensitive', async () => { id: 'child0_child0', isMatch: true, hasChildren: false, - children: null, + children: [], element: state.elements['child0_child0'], axElement: null, }, @@ -260,7 +260,7 @@ test('test the searchNode, it should not be case sensitive', async () => { id: 'child0_child1', isMatch: true, hasChildren: false, - children: null, + children: [], element: state.elements['child0_child1'], axElement: null, }, @@ -277,7 +277,7 @@ test('test the searchNode, it should not be case sensitive', async () => { id: 'child1_child0', isMatch: true, hasChildren: false, - children: null, + children: [], element: state.elements['child1_child0'], axElement: null, }, @@ -293,7 +293,7 @@ test('test the searchNode, it should not be case sensitive', async () => { }); test('test the searchNode for non existent query', async () => { - const searchResult: ?SearchResultTree = await searchNodes( + const searchResult: SearchResultTree | null = await searchNodes( state.elements['root'], 'Unknown query', false, diff --git a/src/plugins/layout/index.js b/src/plugins/layout/index.tsx similarity index 83% rename from src/plugins/layout/index.js rename to src/plugins/layout/index.tsx index 8f4fbecb4..01091e1f1 100644 --- a/src/plugins/layout/index.js +++ b/src/plugins/layout/index.tsx @@ -5,20 +5,16 @@ * @format */ -import type { +import { ElementID, Element, ElementSearchResultSet, MiddlewareAPI, PluginClient, -} from 'flipper'; - -import { FlexColumn, FlexRow, FlipperPlugin, Toolbar, - Sidebar, DetailSidebar, VerticalRule, Button, @@ -29,37 +25,42 @@ import ToolbarIcon from './ToolbarIcon'; import InspectorSidebar from './InspectorSidebar'; import Search from './Search'; import ProxyArchiveClient from './ProxyArchiveClient'; +import React from 'react'; -type State = {| - init: boolean, - inTargetMode: boolean, - inAXMode: boolean, - inAlignmentMode: boolean, - selectedElement: ?ElementID, - selectedAXElement: ?ElementID, - searchResults: ?ElementSearchResultSet, -|}; +type State = { + init: boolean; + inTargetMode: boolean; + inAXMode: boolean; + inAlignmentMode: boolean; + selectedElement: ElementID | null | undefined; + selectedAXElement: ElementID | null | undefined; + searchResults: ElementSearchResultSet | null; +}; -export type ElementMap = {[key: ElementID]: Element}; +export type ElementMap = {[key: string]: Element}; -export type PersistedState = {| - rootElement: ?ElementID, - rootAXElement: ?ElementID, - elements: ElementMap, - AXelements: ElementMap, -|}; +export type PersistedState = { + rootElement: ElementID | null; + rootAXElement: ElementID | null; + elements: ElementMap; + AXelements: ElementMap; +}; -export default class Layout extends FlipperPlugin { - static exportPersistedState = ( - callClient: (string, ?Object) => Promise, - persistedState: ?PersistedState, - store: ?MiddlewareAPI, - ): Promise => { - const defaultPromise = Promise.resolve(persistedState); +export default class Layout extends FlipperPlugin { + static exportPersistedState = async ( + callClient: ( + method: 'getAllNodes', + ) => Promise<{ + allNodes: PersistedState; + }>, + persistedState: PersistedState | undefined, + store: MiddlewareAPI | undefined, + ): Promise => { if (!store) { - return defaultPromise; + return persistedState; } - return callClient('getAllNodes').then(({allNodes}) => allNodes); + const {allNodes} = await callClient('getAllNodes'); + return allNodes; }; static defaultPersistedState = { @@ -69,7 +70,7 @@ export default class Layout extends FlipperPlugin { AXelements: {}, }; - state = { + state: State = { init: false, inTargetMode: false, inAXMode: false, @@ -154,13 +155,12 @@ export default class Layout extends FlipperPlugin { searchResults: this.state.searchResults, }; - let element; - if (this.state.inAXMode && this.state.selectedAXElement) { - element = this.props.persistedState.AXelements[ - this.state.selectedAXElement - ]; - } else if (this.state.selectedElement) { - element = this.props.persistedState.elements[this.state.selectedElement]; + let element: Element | null = null; + const {selectedAXElement, selectedElement, inAXMode} = this.state; + if (inAXMode && selectedAXElement) { + element = this.props.persistedState.AXelements[selectedAXElement]; + } else if (selectedElement) { + element = this.props.persistedState.elements[selectedElement]; } const inspector = ( @@ -247,7 +247,7 @@ export default class Layout extends FlipperPlugin { compact={true} style={{marginTop: 8, marginRight: 12}} onClick={() => { - this.props.selectPlugin('YogaPerformance', element.id); + this.props.selectPlugin('YogaPerformance', element!.id); }}> Analyze Yoga Performance diff --git a/src/plugins/layout/package.json b/src/plugins/layout/package.json index 1a1c9a610..79d8853e9 100644 --- a/src/plugins/layout/package.json +++ b/src/plugins/layout/package.json @@ -1,7 +1,7 @@ { "name": "Inspector", "version": "1.0.0", - "main": "index.js", + "main": "index.tsx", "license": "MIT", "dependencies": { "deep-equal": "^1.0.1", @@ -13,5 +13,8 @@ "bugs": { "email": "oncall+flipper@xmail.facebook.com", "url": "https://fb.workplace.com/groups/230455004101832/" + }, + "devDependencies": { + "@types/lodash.clonedeep": "^4.5.6" } } diff --git a/src/plugins/layout/yarn.lock b/src/plugins/layout/yarn.lock index 78ed2dd38..886b809b3 100644 --- a/src/plugins/layout/yarn.lock +++ b/src/plugins/layout/yarn.lock @@ -2,6 +2,18 @@ # yarn lockfile v1 +"@types/lodash.clonedeep@^4.5.6": + version "4.5.6" + resolved "https://registry.yarnpkg.com/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.6.tgz#3b6c40a0affe0799a2ce823b440a6cf33571d32b" + integrity sha512-cE1jYr2dEg1wBImvXlNtp0xDoS79rfEdGozQVgliDZj1uERH4k+rmEMTudP9b4VQ8O6nRb5gPqft0QzEQGMQgA== + dependencies: + "@types/lodash" "*" + +"@types/lodash@*": + version "4.14.138" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.138.tgz#34f52640d7358230308344e579c15b378d91989e" + integrity sha512-A4uJgHz4hakwNBdHNPdxOTkYmXNgmUAKLbXZ7PKGslgeV0Mb8P3BlbYfPovExek1qnod4pDfRbxuzcVs3dlFLg== + deep-equal@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" diff --git a/tsconfig.json b/tsconfig.json index e8872ee55..e3e47649e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "module": "system", - "lib": ["es7", "dom"], + "lib": ["es7", "dom", "es2017"], "target": "es6", "removeComments": true, "preserveConstEnums": true,