From a7163bf06df5443430cbc3ad8ae00d8e3040e07f Mon Sep 17 00:00:00 2001 From: Chaiwat Ekkaewnumchai Date: Thu, 7 May 2020 03:37:49 -0700 Subject: [PATCH] (server) Add New Parameter And Functions for Select Subscriber Summary: - add type to represent the returned component tree ``` expected data: { [nodeID1]: [subtree1], [nodeID2]: [subtree2], ... } example: { id1: { id2: { id3: { id4: {}, id5: { id6: {} } } } } } ``` - add functions to deal with a tree - `_getElementLeaves` for finding ids that don't have any child given the tree structure - `_getPathForNode` for finding path (similar to previous path parameter) for given id - This diff still retain functionality in case of selector appear to touch only one element. Reviewed By: mweststrate Differential Revision: D21040427 fbshipit-source-id: e6704535a437ad47d9664cc16896b9f24c9d6736 --- desktop/plugins/layout/Inspector.tsx | 52 ++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/desktop/plugins/layout/Inspector.tsx b/desktop/plugins/layout/Inspector.tsx index cf172551c..d71664025 100644 --- a/desktop/plugins/layout/Inspector.tsx +++ b/desktop/plugins/layout/Inspector.tsx @@ -25,6 +25,8 @@ type GetNodesOptions = { forAccessibilityEvent?: boolean; }; +type ElementSelectorNode = {[id: string]: ElementSelectorNode}; + type Props = { ax?: boolean; client: PluginClient; @@ -131,8 +133,12 @@ export default class Inspector extends Component { this.props.client.subscribe( this.call().SELECT, - ({path}: {path: Array}) => { - this.getAndExpandPath(path); + ({path, tree}: {path?: Array; tree?: ElementSelectorNode}) => { + if (tree) { + this._getAndExpandPathFromTree(tree); + } else if (path) { + this.getAndExpandPath(path); + } }, ); @@ -291,6 +297,48 @@ export default class Inspector extends Component { this.onElementSelected(path[path.length - 1]); } + getElementLeaves(tree: ElementSelectorNode): Array { + return tree + ? Object.entries(tree).reduce( + ( + currLeafNode: Array, + [id, children]: [ElementID, ElementSelectorNode], + ): Array => + currLeafNode.concat( + Object.keys(children).length > 0 + ? this.getElementLeaves(children) + : [id], + ), + [], + ) + : []; + } + + /// Return path from given tree structure and id if id is not null; otherwise return any path + getPathForNode( + tree: ElementSelectorNode, + nodeID: ElementID | null, + ): Array | null { + for (const node in tree) { + if ( + node === nodeID || + (nodeID === null && Object.keys(tree[node]).length == 0) + ) { + return [node]; + } + const path = this.getPathForNode(tree[node], nodeID); + if (path !== null) { + return [node].concat(path); + } + } + return null; + } + + // NOTE: this will be used in the future when we remove path and use tree instead + async _getAndExpandPathFromTree(tree: ElementSelectorNode) { + this.getAndExpandPath(this.getPathForNode(tree, null) ?? []); + } + onElementSelected = debounce((selectedKey: ElementID) => { this.onElementHovered(selectedKey); this.props.onSelect(selectedKey);