Two-tree view up and running, separately interactive/editable
Summary: Added duplicate view tree (will be replaced with accessibility node tree eventually). Can toggle ax mode on and off and interact with each tree individually to view/change properties. Reviewed By: danielbuechele Differential Revision: D8717557 fbshipit-source-id: 1109ccafd49b6958ee7a70c2e8851ed8351516ae
This commit is contained in:
committed by
Facebook Github Bot
parent
917376db6d
commit
d8cf48d750
@@ -22,20 +22,23 @@ import {
|
|||||||
SearchInput,
|
SearchInput,
|
||||||
SearchIcon,
|
SearchIcon,
|
||||||
SonarSidebar,
|
SonarSidebar,
|
||||||
|
VerticalRule,
|
||||||
} from 'sonar';
|
} from 'sonar';
|
||||||
|
|
||||||
import {AXElementsInspector} from '../../fb-stubs/AXLayoutExtender.js';
|
import {AXElementsInspector} from '../../fb-stubs/AXLayoutExtender.js';
|
||||||
import config from '../../fb-stubs/config.js';
|
|
||||||
|
|
||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
import debounce from 'lodash.debounce';
|
import debounce from 'lodash.debounce';
|
||||||
|
|
||||||
export type InspectorState = {|
|
export type InspectorState = {|
|
||||||
initialised: boolean,
|
initialised: boolean,
|
||||||
|
AXinitialised: boolean,
|
||||||
selected: ?ElementID,
|
selected: ?ElementID,
|
||||||
selectedAX: ?ElementID,
|
AXselected: ?ElementID,
|
||||||
root: ?ElementID,
|
root: ?ElementID,
|
||||||
|
AXroot: ?ElementID,
|
||||||
elements: {[key: ElementID]: Element},
|
elements: {[key: ElementID]: Element},
|
||||||
|
AXelements: {[key: ElementID]: Element},
|
||||||
isSearchActive: boolean,
|
isSearchActive: boolean,
|
||||||
inAXMode: boolean,
|
inAXMode: boolean,
|
||||||
searchResults: ?ElementSearchResultSet,
|
searchResults: ?ElementSearchResultSet,
|
||||||
@@ -143,12 +146,15 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
|
|
||||||
state = {
|
state = {
|
||||||
elements: {},
|
elements: {},
|
||||||
|
AXelements: {},
|
||||||
initialised: false,
|
initialised: false,
|
||||||
|
AXinitialised: false,
|
||||||
isSearchActive: false,
|
isSearchActive: false,
|
||||||
inAXMode: false,
|
inAXMode: false,
|
||||||
root: null,
|
root: null,
|
||||||
|
AXroot: null,
|
||||||
selected: null,
|
selected: null,
|
||||||
selectedAX: null,
|
AXselected: null,
|
||||||
searchResults: null,
|
searchResults: null,
|
||||||
outstandingSearchQuery: null,
|
outstandingSearchQuery: null,
|
||||||
};
|
};
|
||||||
@@ -162,7 +168,7 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
|
|
||||||
SelectAXElement(state: InspectorState, {key}: SelectElementArgs) {
|
SelectAXElement(state: InspectorState, {key}: SelectElementArgs) {
|
||||||
return {
|
return {
|
||||||
selectedAX: key,
|
AXselected: key,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -178,6 +184,18 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
ExpandAXElement(state: InspectorState, {expand, key}: ExpandElementArgs) {
|
||||||
|
return {
|
||||||
|
AXelements: {
|
||||||
|
...state.AXelements,
|
||||||
|
[key]: {
|
||||||
|
...state.AXelements[key],
|
||||||
|
expanded: expand,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
ExpandElements(state: InspectorState, {elements}: ExpandElementsArgs) {
|
ExpandElements(state: InspectorState, {elements}: ExpandElementsArgs) {
|
||||||
const expandedSet = new Set(elements);
|
const expandedSet = new Set(elements);
|
||||||
const newState = {
|
const newState = {
|
||||||
@@ -194,6 +212,22 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
return newState;
|
return newState;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
ExpandAXElements(state: InspectorState, {elements}: ExpandElementsArgs) {
|
||||||
|
const expandedSet = new Set(elements);
|
||||||
|
const newState = {
|
||||||
|
AXelements: {
|
||||||
|
...state.AXelements,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
for (const key of Object.keys(state.AXelements)) {
|
||||||
|
newState.AXelements[key] = {
|
||||||
|
...newState.AXelements[key],
|
||||||
|
expanded: expandedSet.has(key),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return newState;
|
||||||
|
},
|
||||||
|
|
||||||
UpdateElements(state: InspectorState, {elements}: UpdateElementsArgs) {
|
UpdateElements(state: InspectorState, {elements}: UpdateElementsArgs) {
|
||||||
const updatedElements = state.elements;
|
const updatedElements = state.elements;
|
||||||
|
|
||||||
@@ -209,10 +243,29 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
return {elements: updatedElements};
|
return {elements: updatedElements};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
UpdateAXElements(state: InspectorState, {elements}: UpdateElementsArgs) {
|
||||||
|
const updatedElements = state.AXelements;
|
||||||
|
|
||||||
|
for (const element of elements) {
|
||||||
|
const current = updatedElements[element.id] || {};
|
||||||
|
// $FlowFixMe
|
||||||
|
updatedElements[element.id] = {
|
||||||
|
...current,
|
||||||
|
...element,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {AXelements: updatedElements};
|
||||||
|
},
|
||||||
|
|
||||||
SetRoot(state: InspectorState, {root}: SetRootArgs) {
|
SetRoot(state: InspectorState, {root}: SetRootArgs) {
|
||||||
return {root};
|
return {root};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
SetAXRoot(state: InspectorState, {root}: SetRootArgs) {
|
||||||
|
return {AXroot: root};
|
||||||
|
},
|
||||||
|
|
||||||
SetSearchActive(
|
SetSearchActive(
|
||||||
state: InspectorState,
|
state: InspectorState,
|
||||||
{isSearchActive}: {isSearchActive: boolean},
|
{isSearchActive}: {isSearchActive: boolean},
|
||||||
@@ -240,7 +293,9 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
executeCommand(command: string) {
|
executeCommand(command: string) {
|
||||||
return this.client.call('executeCommand', {
|
return this.client.call('executeCommand', {
|
||||||
command: command,
|
command: command,
|
||||||
context: this.state.selected,
|
context: this.state.inAXMode
|
||||||
|
? this.state.AXselected
|
||||||
|
: this.state.selected,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,16 +303,23 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
* When opening the inspector for the first time, expand all elements that contain only 1 child
|
* When opening the inspector for the first time, expand all elements that contain only 1 child
|
||||||
* recursively.
|
* recursively.
|
||||||
*/
|
*/
|
||||||
async performInitialExpand(element: Element): Promise<void> {
|
async performInitialExpand(element: Element, ax: boolean): Promise<void> {
|
||||||
if (!element.children.length) {
|
if (!element.children.length) {
|
||||||
// element has no children so we're as deep as we can be
|
// element has no children so we're as deep as we can be
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.dispatchAction({expand: true, key: element.id, type: 'ExpandElement'});
|
this.dispatchAction({
|
||||||
|
expand: true,
|
||||||
|
key: element.id,
|
||||||
|
type: ax ? 'ExpandAXElement' : 'ExpandElement',
|
||||||
|
});
|
||||||
|
|
||||||
return this.getChildren(element.id).then((elements: Array<Element>) => {
|
return this.getChildren(element.id, ax).then((elements: Array<Element>) => {
|
||||||
this.dispatchAction({elements, type: 'UpdateElements'});
|
this.dispatchAction({
|
||||||
|
elements,
|
||||||
|
type: ax ? 'UpdateAXElements' : 'UpdateElements',
|
||||||
|
});
|
||||||
|
|
||||||
if (element.children.length >= 2) {
|
if (element.children.length >= 2) {
|
||||||
// element has two or more children so we can stop expanding
|
// element has two or more children so we can stop expanding
|
||||||
@@ -265,7 +327,10 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this.performInitialExpand(
|
return this.performInitialExpand(
|
||||||
this.state.elements[element.children[0]],
|
ax
|
||||||
|
? this.state.AXelements[element.children[0]]
|
||||||
|
: this.state.elements[element.children[0]],
|
||||||
|
ax,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -330,38 +395,50 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
this.client.call('getRoot').then((element: Element) => {
|
this.client.call('getRoot').then((element: Element) => {
|
||||||
this.dispatchAction({elements: [element], type: 'UpdateElements'});
|
this.dispatchAction({elements: [element], type: 'UpdateElements'});
|
||||||
this.dispatchAction({root: element.id, type: 'SetRoot'});
|
this.dispatchAction({root: element.id, type: 'SetRoot'});
|
||||||
this.performInitialExpand(element).then(() => {
|
this.performInitialExpand(element, false).then(() => {
|
||||||
this.props.logger.trackTimeSince('LayoutInspectorInitialize');
|
this.props.logger.trackTimeSince('LayoutInspectorInitialize');
|
||||||
this.setState({initialised: true});
|
this.setState({initialised: true});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.client.call('getRoot').then((element: Element) => {
|
||||||
|
this.dispatchAction({elements: [element], type: 'UpdateAXElements'});
|
||||||
|
this.dispatchAction({root: element.id, type: 'SetAXRoot'});
|
||||||
|
this.performInitialExpand(element, true).then(() => {
|
||||||
|
this.setState({AXinitialised: true});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
this.client.subscribe(
|
this.client.subscribe(
|
||||||
'invalidate',
|
'invalidate',
|
||||||
({nodes}: {nodes: Array<{id: ElementID}>}) => {
|
({nodes}: {nodes: Array<{id: ElementID}>}) => {
|
||||||
this.invalidate(nodes.map(node => node.id)).then(
|
this.invalidate(nodes.map(node => node.id)).then(
|
||||||
(elements: Array<Element>) => {
|
(elements: Array<Element>) => {
|
||||||
this.dispatchAction({elements, type: 'UpdateElements'});
|
this.dispatchAction({elements, type: 'UpdateElements'});
|
||||||
|
// to be removed once trees are separate - will have own invalidate
|
||||||
|
this.dispatchAction({elements, type: 'UpdateAXElements'});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
this.client.subscribe('select', ({path}: {path: Array<ElementID>}) => {
|
this.client.subscribe('select', ({path}: {path: Array<ElementID>}) => {
|
||||||
this.getNodesAndDirectChildren(path).then((elements: Array<Element>) => {
|
this.getNodesAndDirectChildren(path, false).then(
|
||||||
const selected = path[path.length - 1];
|
(elements: Array<Element>) => {
|
||||||
|
const selected = path[path.length - 1];
|
||||||
|
|
||||||
this.dispatchAction({elements, type: 'UpdateElements'});
|
this.dispatchAction({elements, type: 'UpdateElements'});
|
||||||
this.dispatchAction({key: selected, type: 'SelectElement'});
|
this.dispatchAction({key: selected, type: 'SelectElement'});
|
||||||
this.dispatchAction({isSearchActive: false, type: 'SetSearchActive'});
|
this.dispatchAction({isSearchActive: false, type: 'SetSearchActive'});
|
||||||
|
|
||||||
for (const key of path) {
|
for (const key of path) {
|
||||||
this.dispatchAction({expand: true, key, type: 'ExpandElement'});
|
this.dispatchAction({expand: true, key, type: 'ExpandElement'});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.client.send('setHighlighted', {id: selected});
|
this.client.send('setHighlighted', {id: selected});
|
||||||
this.client.send('setSearchActive', {active: false});
|
this.client.send('setSearchActive', {active: false});
|
||||||
});
|
},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,7 +447,7 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
return Promise.resolve([]);
|
return Promise.resolve([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.getNodes(ids, true).then((elements: Array<Element>) => {
|
return this.getNodes(ids, true, false).then((elements: Array<Element>) => {
|
||||||
const children = elements
|
const children = elements
|
||||||
.filter(element => {
|
.filter(element => {
|
||||||
const prev = this.state.elements[element.id];
|
const prev = this.state.elements[element.id];
|
||||||
@@ -385,13 +462,16 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getNodesAndDirectChildren(ids: Array<ElementID>): Promise<Array<Element>> {
|
getNodesAndDirectChildren(
|
||||||
return this.getNodes(ids, false).then((elements: Array<Element>) => {
|
ids: Array<ElementID>,
|
||||||
|
ax: boolean,
|
||||||
|
): Promise<Array<Element>> {
|
||||||
|
return this.getNodes(ids, false, ax).then((elements: Array<Element>) => {
|
||||||
const children = elements
|
const children = elements
|
||||||
.map(element => element.children)
|
.map(element => element.children)
|
||||||
.reduce((acc, val) => acc.concat(val), []);
|
.reduce((acc, val) => acc.concat(val), []);
|
||||||
|
|
||||||
return Promise.all([elements, this.getNodes(children, false)]).then(
|
return Promise.all([elements, this.getNodes(children, false, ax)]).then(
|
||||||
arr => {
|
arr => {
|
||||||
return arr.reduce((acc, val) => acc.concat(val), []);
|
return arr.reduce((acc, val) => acc.concat(val), []);
|
||||||
},
|
},
|
||||||
@@ -399,17 +479,24 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getChildren(key: ElementID): Promise<Array<Element>> {
|
getChildren(key: ElementID, ax: boolean): Promise<Array<Element>> {
|
||||||
return this.getNodes(this.state.elements[key].children, false);
|
return this.getNodes(
|
||||||
|
(ax ? this.state.AXelements : this.state.elements)[key].children,
|
||||||
|
false,
|
||||||
|
ax,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getNodes(
|
getNodes(
|
||||||
ids: Array<ElementID> = [],
|
ids: Array<ElementID> = [],
|
||||||
force: boolean,
|
force: boolean,
|
||||||
|
ax: boolean,
|
||||||
): Promise<Array<Element>> {
|
): Promise<Array<Element>> {
|
||||||
if (!force) {
|
if (!force) {
|
||||||
ids = ids.filter(id => {
|
ids = ids.filter(id => {
|
||||||
return this.state.elements[id] === undefined;
|
return (
|
||||||
|
(ax ? this.state.AXelements : this.state.elements)[id] === undefined
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,25 +513,35 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isExpanded(key: ElementID): boolean {
|
isExpanded(key: ElementID, ax: boolean): boolean {
|
||||||
return this.state.elements[key].expanded;
|
return ax
|
||||||
|
? this.state.AXelements[key].expanded
|
||||||
|
: this.state.elements[key].expanded;
|
||||||
}
|
}
|
||||||
|
|
||||||
expandElement = (key: ElementID): Promise<Array<Element>> => {
|
expandElement = (key: ElementID, ax: boolean): Promise<Array<Element>> => {
|
||||||
const expand = !this.isExpanded(key);
|
const expand = !this.isExpanded(key, ax);
|
||||||
return this.setElementExpanded(key, expand);
|
return this.setElementExpanded(key, expand, ax);
|
||||||
};
|
};
|
||||||
|
|
||||||
setElementExpanded = (
|
setElementExpanded = (
|
||||||
key: ElementID,
|
key: ElementID,
|
||||||
expand: boolean,
|
expand: boolean,
|
||||||
|
ax: boolean,
|
||||||
): Promise<Array<Element>> => {
|
): Promise<Array<Element>> => {
|
||||||
this.dispatchAction({expand, key, type: 'ExpandElement'});
|
this.dispatchAction({
|
||||||
|
expand,
|
||||||
|
key,
|
||||||
|
type: ax ? 'ExpandAXElement' : 'ExpandElement',
|
||||||
|
});
|
||||||
performance.mark('LayoutInspectorExpandElement');
|
performance.mark('LayoutInspectorExpandElement');
|
||||||
if (expand) {
|
if (expand) {
|
||||||
return this.getChildren(key).then((elements: Array<Element>) => {
|
return this.getChildren(key, ax).then((elements: Array<Element>) => {
|
||||||
this.props.logger.trackTimeSince('LayoutInspectorExpandElement');
|
this.props.logger.trackTimeSince('LayoutInspectorExpandElement');
|
||||||
this.dispatchAction({elements, type: 'UpdateElements'});
|
this.dispatchAction({
|
||||||
|
elements,
|
||||||
|
type: ax ? 'UpdateAXElements' : 'UpdateElements',
|
||||||
|
});
|
||||||
return Promise.resolve(elements);
|
return Promise.resolve(elements);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -452,11 +549,11 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
deepExpandElement = async (key: ElementID) => {
|
deepExpandElement = async (key: ElementID, ax: boolean) => {
|
||||||
const expand = !this.isExpanded(key);
|
const expand = !this.isExpanded(key, ax);
|
||||||
if (!expand) {
|
if (!expand) {
|
||||||
// we never deep unexpand
|
// we never deep unexpand
|
||||||
return this.setElementExpanded(key, false);
|
return this.setElementExpanded(key, false, ax);
|
||||||
}
|
}
|
||||||
|
|
||||||
// queue of keys to open
|
// queue of keys to open
|
||||||
@@ -469,7 +566,7 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
const key = keys.shift();
|
const key = keys.shift();
|
||||||
|
|
||||||
// expand current element
|
// expand current element
|
||||||
const children = await this.setElementExpanded(key, true);
|
const children = await this.setElementExpanded(key, true, ax);
|
||||||
|
|
||||||
// and add it's children to the queue
|
// and add it's children to the queue
|
||||||
for (const child of children) {
|
for (const child of children) {
|
||||||
@@ -482,9 +579,21 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
|
|
||||||
onElementExpanded = (key: ElementID, deep: boolean) => {
|
onElementExpanded = (key: ElementID, deep: boolean) => {
|
||||||
if (deep) {
|
if (deep) {
|
||||||
this.deepExpandElement(key);
|
this.deepExpandElement(key, false);
|
||||||
} else {
|
} else {
|
||||||
this.expandElement(key);
|
this.expandElement(key, false);
|
||||||
|
}
|
||||||
|
this.props.logger.track('usage', 'layout:element-expanded', {
|
||||||
|
id: key,
|
||||||
|
deep: deep,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onAXElementExpanded = (key: ElementID, deep: boolean) => {
|
||||||
|
if (deep) {
|
||||||
|
this.deepExpandElement(key, true);
|
||||||
|
} else {
|
||||||
|
this.expandElement(key, true);
|
||||||
}
|
}
|
||||||
this.props.logger.track('usage', 'layout:element-expanded', {
|
this.props.logger.track('usage', 'layout:element-expanded', {
|
||||||
id: key,
|
id: key,
|
||||||
@@ -498,20 +607,15 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
this.client.send('setSearchActive', {active: isSearchActive});
|
this.client.send('setSearchActive', {active: isSearchActive});
|
||||||
};
|
};
|
||||||
|
|
||||||
onTestToggleAccessibility = () => {
|
onToggleAccessibility = () => {
|
||||||
const inAXMode = !this.state.inAXMode;
|
const inAXMode = !this.state.inAXMode;
|
||||||
this.dispatchAction({inAXMode, type: 'SetAXMode'});
|
this.dispatchAction({inAXMode, type: 'SetAXMode'});
|
||||||
this.client
|
|
||||||
.call('testAccessibility', {active: inAXMode})
|
|
||||||
.then(({message}: {message: string}) => {
|
|
||||||
console.log(message);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onElementSelected = debounce((key: ElementID) => {
|
onElementSelected = debounce((key: ElementID) => {
|
||||||
this.dispatchAction({key, type: 'SelectElement'});
|
this.dispatchAction({key, type: 'SelectElement'});
|
||||||
this.client.send('setHighlighted', {id: key});
|
this.client.send('setHighlighted', {id: key});
|
||||||
this.getNodes([key], true).then((elements: Array<Element>) => {
|
this.getNodes([key], true, false).then((elements: Array<Element>) => {
|
||||||
this.dispatchAction({elements, type: 'UpdateElements'});
|
this.dispatchAction({elements, type: 'UpdateElements'});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -519,8 +623,8 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
onAXElementSelected = debounce((key: ElementID) => {
|
onAXElementSelected = debounce((key: ElementID) => {
|
||||||
this.dispatchAction({key, type: 'SelectAXElement'});
|
this.dispatchAction({key, type: 'SelectAXElement'});
|
||||||
this.client.send('setHighlighted', {id: key});
|
this.client.send('setHighlighted', {id: key});
|
||||||
this.getNodes([key], true).then((elements: Array<Element>) => {
|
this.getNodes([key], true, true).then((elements: Array<Element>) => {
|
||||||
this.dispatchAction({elements, type: 'UpdateElements'});
|
this.dispatchAction({elements, type: 'UpdateAXElements'});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -530,7 +634,7 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
|
|
||||||
onDataValueChanged = (path: Array<string>, value: any) => {
|
onDataValueChanged = (path: Array<string>, value: any) => {
|
||||||
const selected = this.state.inAXMode
|
const selected = this.state.inAXMode
|
||||||
? this.state.selectedAX
|
? this.state.AXselected
|
||||||
: this.state.selected;
|
: this.state.selected;
|
||||||
this.client.send('setData', {id: selected, path, value});
|
this.client.send('setData', {id: selected, path, value});
|
||||||
this.props.logger.track('usage', 'layout:value-changed', {
|
this.props.logger.track('usage', 'layout:value-changed', {
|
||||||
@@ -541,32 +645,41 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
renderSidebar = () => {
|
renderSidebar = () => {
|
||||||
return this.state.selected != null ? (
|
if (this.state.inAXMode) {
|
||||||
<InspectorSidebar
|
// empty if no element selected w/in AX node tree
|
||||||
element={this.state.elements[this.state.selected]}
|
return (
|
||||||
onValueChanged={this.onDataValueChanged}
|
this.state.AXselected && (
|
||||||
client={this.client}
|
<InspectorSidebar
|
||||||
/>
|
element={this.state.AXelements[this.state.AXselected]}
|
||||||
) : null;
|
onValueChanged={this.onDataValueChanged}
|
||||||
};
|
client={this.client}
|
||||||
|
/>
|
||||||
renderAXSidebar = () => {
|
)
|
||||||
return this.state.selectedAX != null ? (
|
);
|
||||||
<InspectorSidebar
|
} else {
|
||||||
element={this.state.elements[this.state.selectedAX]}
|
// empty if no element selected w/in view tree
|
||||||
onValueChanged={this.onDataValueChanged}
|
return (
|
||||||
client={this.client}
|
this.state.selected != null && (
|
||||||
/>
|
<InspectorSidebar
|
||||||
) : null;
|
element={this.state.elements[this.state.selected]}
|
||||||
|
onValueChanged={this.onDataValueChanged}
|
||||||
|
client={this.client}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
initialised,
|
initialised,
|
||||||
|
AXinitialised,
|
||||||
selected,
|
selected,
|
||||||
selectedAX,
|
AXselected,
|
||||||
root,
|
root,
|
||||||
|
AXroot,
|
||||||
elements,
|
elements,
|
||||||
|
AXelements,
|
||||||
isSearchActive,
|
isSearchActive,
|
||||||
inAXMode,
|
inAXMode,
|
||||||
outstandingSearchQuery,
|
outstandingSearchQuery,
|
||||||
@@ -576,12 +689,12 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
<AXElementsInspector
|
<AXElementsInspector
|
||||||
onElementSelected={this.onAXElementSelected}
|
onElementSelected={this.onAXElementSelected}
|
||||||
onElementHovered={this.onElementHovered}
|
onElementHovered={this.onElementHovered}
|
||||||
onElementExpanded={this.onElementExpanded}
|
onElementExpanded={this.onAXElementExpanded}
|
||||||
onValueChanged={this.onDataValueChanged}
|
onValueChanged={this.onDataValueChanged}
|
||||||
selected={selectedAX}
|
selected={AXselected}
|
||||||
searchResults={this.state.searchResults}
|
searchResults={this.state.searchResults}
|
||||||
root={root}
|
root={AXroot}
|
||||||
elements={elements}
|
elements={AXelements}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
const AXButtonVisible = AXInspector !== null;
|
const AXButtonVisible = AXInspector !== null;
|
||||||
@@ -590,7 +703,7 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
<FlexColumn fill={true}>
|
<FlexColumn fill={true}>
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<SearchIconContainer
|
<SearchIconContainer
|
||||||
onClick={this.onFindClick}
|
onClick={inAXMode ? null : this.onFindClick}
|
||||||
role="button"
|
role="button"
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
title="Select an element on the device to inspect it">
|
title="Select an element on the device to inspect it">
|
||||||
@@ -606,7 +719,7 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
</SearchIconContainer>
|
</SearchIconContainer>
|
||||||
{AXButtonVisible ? (
|
{AXButtonVisible ? (
|
||||||
<SearchIconContainer
|
<SearchIconContainer
|
||||||
onClick={this.onTestToggleAccessibility}
|
onClick={this.onToggleAccessibility}
|
||||||
role="button"
|
role="button"
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
title="Toggle accessibility mode within the LayoutInspector">
|
title="Toggle accessibility mode within the LayoutInspector">
|
||||||
@@ -648,11 +761,10 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
<LoadingIndicator />
|
<LoadingIndicator />
|
||||||
</Center>
|
</Center>
|
||||||
)}
|
)}
|
||||||
{initialised && inAXMode ? AXInspector : null}
|
{AXinitialised && inAXMode ? <VerticalRule /> : null}
|
||||||
|
{AXinitialised && inAXMode ? AXInspector : null}
|
||||||
</FlexRow>
|
</FlexRow>
|
||||||
<SonarSidebar>
|
<SonarSidebar>{this.renderSidebar()}</SonarSidebar>
|
||||||
{inAXMode ? this.renderAXSidebar() : this.renderSidebar()}
|
|
||||||
</SonarSidebar>
|
|
||||||
</FlexColumn>
|
</FlexColumn>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
14
src/ui/components/VerticalRule.js
Normal file
14
src/ui/components/VerticalRule.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2018-present Facebook.
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
* @format
|
||||||
|
*/
|
||||||
|
|
||||||
|
import styled from '../styled/index.js';
|
||||||
|
|
||||||
|
export default styled.view({
|
||||||
|
backgroundColor: '#c9ced4',
|
||||||
|
width: 3,
|
||||||
|
margin: '0',
|
||||||
|
});
|
||||||
@@ -128,6 +128,7 @@ export {default as ResizeSensor} from './components/ResizeSensor.js';
|
|||||||
|
|
||||||
// typhography
|
// typhography
|
||||||
export {default as HorizontalRule} from './components/HorizontalRule.js';
|
export {default as HorizontalRule} from './components/HorizontalRule.js';
|
||||||
|
export {default as VerticalRule} from './components/VerticalRule.js';
|
||||||
export {default as Label} from './components/Label.js';
|
export {default as Label} from './components/Label.js';
|
||||||
export {default as Heading} from './components/Heading.js';
|
export {default as Heading} from './components/Heading.js';
|
||||||
|
|
||||||
@@ -154,6 +155,7 @@ export type {
|
|||||||
Element,
|
Element,
|
||||||
ElementSearchResultSet,
|
ElementSearchResultSet,
|
||||||
} from './components/elements-inspector/ElementsInspector.js';
|
} from './components/elements-inspector/ElementsInspector.js';
|
||||||
|
export {Elements} from './components/elements-inspector/elements.js';
|
||||||
export {
|
export {
|
||||||
default as ElementsInspector,
|
default as ElementsInspector,
|
||||||
} from './components/elements-inspector/ElementsInspector.js';
|
} from './components/elements-inspector/ElementsInspector.js';
|
||||||
|
|||||||
Reference in New Issue
Block a user