Implementing Layout Inspection
To enable the Flipper Layout Inspector on a new platform, just implement a client plugin with id Inspector
that implements the interface detailed in this page.
The Flow syntax is used to specify this JSON API.
Nodeβ
Node is the core data type of the layout inspector. The Flipper desktop plugin visualizes a tree of nodes with associated data and attributes. Any UI or data model which can be modeled as a tree of nodes can be inspected using the layout inspector. Data associated with the nodes can also be edited.
type NodeId = string;
type InspectorValue = {
__type__: 'auto' | 'text' | 'number' | 'boolean' | 'enum' | 'color',
__mutable__: boolean,
value: number | string | boolean,
};
type Node = {
id: NodeId,
name: string,
data: ?{string: Object},
children: Array<NodeId>,
attributes: ?Array<{name: string, value: string}>,
decoration: ?string,
};
Node Parametersβ
Following is a description of the parameters used in the above node:
id
- a stable, globally unique, node identifier.name
- the user-facing identifier for this node. It does not need to be unique. Typically, the class name of the node is used as the node's name.data
- a set of named JSON objects representing data associated with the node. This 'data' is rendered as immutable, by default, to the user of the plugin but can be made mutable by wrapping any value in a 'InspectorValue' with the__mutable__
attribute set to true.- The 'InspectorValue' can also be used to change the parsed type of the value, such as parsing a number as a color to show the value in a color picker.
children
- a list of identifiers pointing to children of this node. This is a list of identifiers instead of a list of nodes to allow nodes to be lazily fetched and instantiated.attributes
- a list of key-value pairs, which are displayed alongside the name in the Layout Inspector.decoration
- a string identifying the optional icon used to decorate a node in the Layout Inspector. Adding new decoration options requires adding an icon file to the Sonar desktop app. Currently, ComponentKit and Litho decorations are supported.
Plugin Interfaceβ
interface ClientLayoutPlugin {
Node getRoot();
GetNodesResponse getNodes({ids: Array<NodeId>});
GetAllNodesResponse getAllNodes();
void setData({id: NodeId, path: Array<string>, value: any});
void setHighlighted({id: ?NodeId});
void setSearchActive({active: boolean});
GetSearchResultsResponse getSearchResults({query: string});
};
interface DesktopLayoutPlugin {
void invalidate({id: NodeId});
void select({path: Array<NodeId>});
};
type GetNodesResponse = {
elements: Array<Node>
};
type GetAllNodesResponse = {
elements: Array<Node>,
rootElement: NodeId
};
type GetSearchResultsResponse = {
results: ?SearchResultNode,
query: string
};
type SearchResultNode = {
id: NodeId,
isMatch: boolean,
element: Node,
children: ?Array<SearchResultNode>
}
type NodeId = string;
Interface methodsβ
getRoot
- returns the root node of your hierarchy. This is the entry point of Flipper's traversal of your layout.getNodes
- maps a set of Node Ids to their corresponding nodes. This call is used to, among other things, query the children of a node.getAllNodes
- similar to 'getNodes', this should return all nodes in the current layout tree. Ordinarily, nodes are requested lazily, however this exists for taking snapshots of the current state.setData
- set the data of an mutable data object returned as part of the data field of a node:- The
id
parameter identifies the node. - The
path
parameter is an index path into an object, such as['bounds', 'left']
. - The
value
parameter is a value of appropriate type to be used as an override.
- The
setHighlighted
- marks a node as highlighted. It is expected that implementations add a colored overlay to the node identified by id on screen, so that as the user browses the layout tree in Flipper, they can easily see on the client display the nodes with which they are interacting. Passing a null id parameter removes the current highlight without highlighting a new node.setSearchActive
- the user has clicked on the crosshair button in Sonar. This feature allows the user to click on an element in the client UI to cause Flipper to highlight the corresponding node in the layout tree. A colored overlay should be shown over the whole screen untilsetSearchActive
is called withactive: false
. WhilesetSearchActive
is true. Clicking an element in the client UI should trigger aselect
call to the Flipper desktop, with the path of ids from root to selected node, for example,select(['node1', 'node6', 'node65'])
to select a grandchild ofnode1
.getSearchResults
- executes a query on all nodes in the tree and returns a subtree of the layout tree that contains all matching nodes and those on the path from root. A parent that does not itself match the query but exists on the path to a node that does, should have the attributeisMatch: false
and only the matching nodes should haveisMatch: true
. Nodes not on the path from root to a match need not be included in the returned tree. Be careful not to confuse this method with the unrelatedsetSearchActive
, which unfortunately shares a similar name.
Whenever a node or subtree changes, it is expected that the client sends a invalidate
command to the desktop app over the active connection. This invalidates the cache of the subtree anchored by the node with the given id.