basic layout edits

Summary: Include toggle button, trees/sidebar not separately interactive

Reviewed By: danielbuechele

Differential Revision: D8680613

fbshipit-source-id: 3bc52b66881abc56ea5cc0955f8237509d039fc4
This commit is contained in:
Sara Valderrama
2018-07-05 16:18:31 -07:00
committed by Facebook Github Bot
parent 3833f061e2
commit 917376db6d
2 changed files with 112 additions and 3 deletions

View File

@@ -0,0 +1,25 @@
/**
* 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 {Component} from 'react';
import type {Element, ElementID, ElementSearchResultSet} from 'sonar';
export class AXElementsInspector extends Component<{
onElementExpanded: (key: ElementID, deep: boolean) => void,
onElementSelected: (key: ElementID) => void,
onElementHovered: ?(key: ?ElementID) => void,
onValueChanged: ?(path: Array<string>, val: any) => void,
selected: ?ElementID,
searchResults?: ?ElementSearchResultSet,
root: ?ElementID,
elements: {[key: ElementID]: Element},
useAppSidebar?: boolean,
}> {
render() {
return null;
}
}

View File

@@ -24,15 +24,20 @@ import {
SonarSidebar, SonarSidebar,
} from 'sonar'; } from 'sonar';
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,
selected: ?ElementID, selected: ?ElementID,
selectedAX: ?ElementID,
root: ?ElementID, root: ?ElementID,
elements: {[key: ElementID]: Element}, elements: {[key: ElementID]: Element},
isSearchActive: boolean, isSearchActive: boolean,
inAXMode: boolean,
searchResults: ?ElementSearchResultSet, searchResults: ?ElementSearchResultSet,
outstandingSearchQuery: ?string, outstandingSearchQuery: ?string,
|}; |};
@@ -140,8 +145,10 @@ export default class Layout extends SonarPlugin<InspectorState> {
elements: {}, elements: {},
initialised: false, initialised: false,
isSearchActive: false, isSearchActive: false,
inAXMode: false,
root: null, root: null,
selected: null, selected: null,
selectedAX: null,
searchResults: null, searchResults: null,
outstandingSearchQuery: null, outstandingSearchQuery: null,
}; };
@@ -153,6 +160,12 @@ export default class Layout extends SonarPlugin<InspectorState> {
}; };
}, },
SelectAXElement(state: InspectorState, {key}: SelectElementArgs) {
return {
selectedAX: key,
};
},
ExpandElement(state: InspectorState, {expand, key}: ExpandElementArgs) { ExpandElement(state: InspectorState, {expand, key}: ExpandElementArgs) {
return { return {
elements: { elements: {
@@ -206,6 +219,10 @@ export default class Layout extends SonarPlugin<InspectorState> {
) { ) {
return {isSearchActive}; return {isSearchActive};
}, },
SetAXMode(state: InspectorState, {inAXMode}: {inAXMode: boolean}) {
return {inAXMode};
},
}; };
search(query: string) { search(query: string) {
@@ -481,6 +498,16 @@ export default class Layout extends SonarPlugin<InspectorState> {
this.client.send('setSearchActive', {active: isSearchActive}); this.client.send('setSearchActive', {active: isSearchActive});
}; };
onTestToggleAccessibility = () => {
const inAXMode = !this.state.inAXMode;
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});
@@ -489,14 +516,25 @@ export default class Layout extends SonarPlugin<InspectorState> {
}); });
}); });
onAXElementSelected = debounce((key: ElementID) => {
this.dispatchAction({key, type: 'SelectAXElement'});
this.client.send('setHighlighted', {id: key});
this.getNodes([key], true).then((elements: Array<Element>) => {
this.dispatchAction({elements, type: 'UpdateElements'});
});
});
onElementHovered = debounce((key: ?ElementID) => { onElementHovered = debounce((key: ?ElementID) => {
this.client.send('setHighlighted', {id: key}); this.client.send('setHighlighted', {id: key});
}); });
onDataValueChanged = (path: Array<string>, value: any) => { onDataValueChanged = (path: Array<string>, value: any) => {
this.client.send('setData', {id: this.state.selected, path, value}); const selected = this.state.inAXMode
? this.state.selectedAX
: this.state.selected;
this.client.send('setData', {id: selected, path, value});
this.props.logger.track('usage', 'layout:value-changed', { this.props.logger.track('usage', 'layout:value-changed', {
id: this.state.selected, id: selected,
value: value, value: value,
path: path, path: path,
}); });
@@ -512,16 +550,42 @@ export default class Layout extends SonarPlugin<InspectorState> {
) : null; ) : null;
}; };
renderAXSidebar = () => {
return this.state.selectedAX != null ? (
<InspectorSidebar
element={this.state.elements[this.state.selectedAX]}
onValueChanged={this.onDataValueChanged}
client={this.client}
/>
) : null;
};
render() { render() {
const { const {
initialised, initialised,
selected, selected,
selectedAX,
root, root,
elements, elements,
isSearchActive, isSearchActive,
inAXMode,
outstandingSearchQuery, outstandingSearchQuery,
} = this.state; } = this.state;
const AXInspector = (
<AXElementsInspector
onElementSelected={this.onAXElementSelected}
onElementHovered={this.onElementHovered}
onElementExpanded={this.onElementExpanded}
onValueChanged={this.onDataValueChanged}
selected={selectedAX}
searchResults={this.state.searchResults}
root={root}
elements={elements}
/>
);
const AXButtonVisible = AXInspector !== null;
return ( return (
<FlexColumn fill={true}> <FlexColumn fill={true}>
<Toolbar> <Toolbar>
@@ -540,6 +604,23 @@ export default class Layout extends SonarPlugin<InspectorState> {
} }
/> />
</SearchIconContainer> </SearchIconContainer>
{AXButtonVisible ? (
<SearchIconContainer
onClick={this.onTestToggleAccessibility}
role="button"
tabIndex={-1}
title="Toggle accessibility mode within the LayoutInspector">
<Glyph
name="accessibility"
size={16}
color={
inAXMode
? colors.macOSTitleBarIconSelected
: colors.macOSTitleBarIconActive
}
/>
</SearchIconContainer>
) : null}
<SearchBox tabIndex={-1}> <SearchBox tabIndex={-1}>
<SearchIcon <SearchIcon
name="magnifying-glass" name="magnifying-glass"
@@ -567,8 +648,11 @@ export default class Layout extends SonarPlugin<InspectorState> {
<LoadingIndicator /> <LoadingIndicator />
</Center> </Center>
)} )}
{initialised && inAXMode ? AXInspector : null}
</FlexRow> </FlexRow>
<SonarSidebar>{this.renderSidebar()}</SonarSidebar> <SonarSidebar>
{inAXMode ? this.renderAXSidebar() : this.renderSidebar()}
</SonarSidebar>
</FlexColumn> </FlexColumn>
); );
} }