convert Layout plugin
Summary: _typescript_ Reviewed By: passy Differential Revision: D17153997 fbshipit-source-id: 308a070b86430a9256beb93b4d3e5f8d5b6c6e52
This commit is contained in:
committed by
Facebook Github Bot
parent
705ba8eaa8
commit
ef2c6787fa
@@ -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
|
||||
>;
|
||||
|
||||
@@ -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<string>, value: any) => void,
|
||||
setPersistedState: (state: $Shape<PersistedState>) => 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<string>, value: any) => void;
|
||||
setPersistedState: (state: Partial<PersistedState>) => void;
|
||||
persistedState: PersistedState;
|
||||
searchResults: ElementSearchResultSet | null;
|
||||
};
|
||||
|
||||
export default class Inspector extends Component<Props> {
|
||||
@@ -76,8 +76,12 @@ export default class Inspector extends Component<Props> {
|
||||
const elements: Array<Element> = 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<Props> {
|
||||
({
|
||||
nodes,
|
||||
}: {
|
||||
nodes: Array<{id: ElementID, children: Array<ElementID>}>,
|
||||
nodes: Array<{id: ElementID; children: Array<ElementID>}>;
|
||||
}) => {
|
||||
const ids = nodes
|
||||
.map(n => [n.id, ...(n.children || [])])
|
||||
@@ -154,7 +158,11 @@ export default class Inspector extends Component<Props> {
|
||||
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<Props> {
|
||||
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<Props> {
|
||||
(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<Props> {
|
||||
});
|
||||
}
|
||||
|
||||
invalidate(ids: Array<ElementID>): Promise<Array<Element>> {
|
||||
async invalidate(ids: Array<ElementID>): Promise<Array<Element>> {
|
||||
if (ids.length === 0) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
return this.getNodes(ids, {}).then((elements: Array<Element>) => {
|
||||
const elements = await this.getNodes(ids, {});
|
||||
const children = elements
|
||||
.filter((element: Element) => this.elements()[element.id]?.expanded)
|
||||
.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<Props> {
|
||||
// element has no children so we're as deep as we can be
|
||||
return;
|
||||
}
|
||||
return this.getChildren(element.id, {}).then((elements: Array<Element>) => {
|
||||
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<Props> {
|
||||
return this.getNodes(this.elements()[id].children, options);
|
||||
}
|
||||
|
||||
getNodes(
|
||||
async getNodes(
|
||||
ids: Array<ElementID> = [],
|
||||
options: GetNodesOptions,
|
||||
): Promise<Array<Element>> {
|
||||
const {forAccessibilityEvent} = options;
|
||||
|
||||
if (ids.length > 0) {
|
||||
return this.props.client
|
||||
.call(this.call().GET_NODES, {
|
||||
const {forAccessibilityEvent} = options;
|
||||
const {
|
||||
elements,
|
||||
}: {elements: Array<Element>} = 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;
|
||||
});
|
||||
} else {
|
||||
return Promise.resolve([]);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
getAndExpandPath(path: Array<ElementID>) {
|
||||
return Promise.all(path.map(id => this.getChildren(id, {}))).then(() => {
|
||||
async getAndExpandPath(path: Array<ElementID>) {
|
||||
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<Props> {
|
||||
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,
|
||||
@@ -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<string>, 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<InspectorSidebarSectionProps> {
|
||||
@@ -51,7 +50,7 @@ class InspectorSidebarSection extends Component<InspectorSidebarSectionProps> {
|
||||
);
|
||||
}
|
||||
|
||||
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<InspectorSidebarSectionProps> {
|
||||
}
|
||||
}
|
||||
|
||||
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<Props> {
|
||||
render() {
|
||||
@@ -115,12 +114,13 @@ export default class Sidebar extends Component<Props> {
|
||||
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<Props> {
|
||||
);
|
||||
data = {};
|
||||
}
|
||||
} else {
|
||||
data = section;
|
||||
}
|
||||
sections.push(
|
||||
<InspectorSidebarSection
|
||||
@@ -5,15 +5,18 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
import type {Element, ElementID} from 'flipper';
|
||||
import type {PersistedState} from './index';
|
||||
import type {SearchResultTree} from './Search';
|
||||
// $FlowFixMe
|
||||
import {Element} from 'flipper';
|
||||
import {PersistedState} from './index';
|
||||
import {SearchResultTree} from './Search';
|
||||
import cloneDeep from 'lodash.clonedeep';
|
||||
|
||||
const propsForPersistedState = (
|
||||
AXMode: boolean,
|
||||
): {ROOT: string, ELEMENTS: string, ELEMENT: string} => {
|
||||
): {
|
||||
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<SearchResultTree>,
|
||||
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<boolean> {
|
||||
supportsMethod(_method: string): Promise<boolean> {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
send(method: string, params?: Object): void {
|
||||
send(_method: string, _params?: Object): void {
|
||||
return;
|
||||
}
|
||||
|
||||
call(method: string, params?: Object): Promise<any> {
|
||||
const paramaters = params;
|
||||
call(method: string, paramaters?: {[key: string]: any}): Promise<any> {
|
||||
switch (method) {
|
||||
case 'getRoot': {
|
||||
const {rootElement} = this.persistedState;
|
||||
@@ -118,7 +120,7 @@ class ProxyArchiveClient {
|
||||
}
|
||||
const {ids} = paramaters;
|
||||
const arr: Array<Element> = [];
|
||||
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<Element> = [];
|
||||
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'));
|
||||
@@ -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<SearchResultTree>,
|
||||
element: Element,
|
||||
axElement: ?Element, // Not supported in iOS
|
||||
|};
|
||||
export type SearchResultTree = {
|
||||
id: string;
|
||||
isMatch: boolean;
|
||||
hasChildren: boolean;
|
||||
children: Array<SearchResultTree>;
|
||||
element: Element;
|
||||
axElement: Element | null; // Not supported in iOS
|
||||
};
|
||||
|
||||
type Props = {
|
||||
client: PluginClient,
|
||||
inAXMode: boolean,
|
||||
onSearchResults: (searchResults: ElementSearchResultSet) => void,
|
||||
setPersistedState: (state: $Shape<PersistedState>) => void,
|
||||
persistedState: PersistedState,
|
||||
initialQuery: ?string,
|
||||
client: PluginClient;
|
||||
inAXMode: boolean;
|
||||
onSearchResults: (searchResults: ElementSearchResultSet) => void;
|
||||
setPersistedState: (state: Partial<PersistedState>) => 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<Props, State> {
|
||||
outstandingSearchQuery: null,
|
||||
};
|
||||
|
||||
timer: TimeoutID;
|
||||
timer: NodeJS.Timeout | undefined;
|
||||
|
||||
onChange = (e: SyntheticInputEvent<>) => {
|
||||
onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
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<Props, State> {
|
||||
const queryString = this.props.initialQuery
|
||||
? this.props.initialQuery
|
||||
: '';
|
||||
if (this.timer) {
|
||||
clearTimeout(this.timer);
|
||||
}
|
||||
this.timer = setTimeout(() => this.performSearch(queryString), 200);
|
||||
}
|
||||
}
|
||||
@@ -102,8 +108,8 @@ export default class Search extends Component<Props, State> {
|
||||
results,
|
||||
query,
|
||||
}: {
|
||||
results: ?SearchResultTree,
|
||||
query: string,
|
||||
results: SearchResultTree | null;
|
||||
query: string;
|
||||
},
|
||||
axMode: boolean,
|
||||
) {
|
||||
@@ -159,13 +165,14 @@ export default class Search extends Component<Props, State> {
|
||||
}
|
||||
|
||||
getElementsFromSearchResultTree(
|
||||
tree: ?SearchResultTree,
|
||||
tree: SearchResultTree | null,
|
||||
): Array<SearchResultTree> {
|
||||
if (!tree) {
|
||||
return [];
|
||||
}
|
||||
let elements = [
|
||||
{
|
||||
children: [] as Array<SearchResultTree>,
|
||||
id: tree.id,
|
||||
isMatch: tree.isMatch,
|
||||
hasChildren: Boolean(tree.children),
|
||||
@@ -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,
|
||||
@@ -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,
|
||||
@@ -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<State, void, PersistedState> {
|
||||
static exportPersistedState = (
|
||||
callClient: (string, ?Object) => Promise<Object>,
|
||||
persistedState: ?PersistedState,
|
||||
store: ?MiddlewareAPI,
|
||||
): Promise<?PersistedState> => {
|
||||
const defaultPromise = Promise.resolve(persistedState);
|
||||
export default class Layout extends FlipperPlugin<State, any, PersistedState> {
|
||||
static exportPersistedState = async (
|
||||
callClient: (
|
||||
method: 'getAllNodes',
|
||||
) => Promise<{
|
||||
allNodes: PersistedState;
|
||||
}>,
|
||||
persistedState: PersistedState | undefined,
|
||||
store: MiddlewareAPI | undefined,
|
||||
): Promise<PersistedState | undefined> => {
|
||||
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<State, void, PersistedState> {
|
||||
AXelements: {},
|
||||
};
|
||||
|
||||
state = {
|
||||
state: State = {
|
||||
init: false,
|
||||
inTargetMode: false,
|
||||
inAXMode: false,
|
||||
@@ -154,13 +155,12 @@ export default class Layout extends FlipperPlugin<State, void, PersistedState> {
|
||||
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<State, void, PersistedState> {
|
||||
compact={true}
|
||||
style={{marginTop: 8, marginRight: 12}}
|
||||
onClick={() => {
|
||||
this.props.selectPlugin('YogaPerformance', element.id);
|
||||
this.props.selectPlugin('YogaPerformance', element!.id);
|
||||
}}>
|
||||
Analyze Yoga Performance
|
||||
</Button>
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "system",
|
||||
"lib": ["es7", "dom"],
|
||||
"lib": ["es7", "dom", "es2017"],
|
||||
"target": "es6",
|
||||
"removeComments": true,
|
||||
"preserveConstEnums": true,
|
||||
|
||||
Reference in New Issue
Block a user