Move plugins to "sonar/desktop/plugins"

Summary:
Plugins moved from "sonar/desktop/src/plugins" to "sonar/desktop/plugins".

Fixed all the paths after moving.

New "desktop" folder structure:
- `src` - Flipper desktop app JS code executing in Electron Renderer (Chrome) process.
- `static` - Flipper desktop app JS code executing in Electron Main (Node.js) process.
- `plugins` - Flipper desktop JS plugins.
- `pkg` - Flipper packaging lib and CLI tool.
- `doctor` - Flipper diagnostics lib and CLI tool.
- `scripts` - Build scripts for Flipper desktop app.
- `headless` - Headless version of Flipper desktop app.
- `headless-tests` - Integration tests running agains Flipper headless version.

Reviewed By: mweststrate

Differential Revision: D20344186

fbshipit-source-id: d020da970b2ea1e001f9061a8782bfeb54e31ba0
This commit is contained in:
Anton Nikolaev
2020-03-14 14:26:07 -07:00
committed by Facebook GitHub Bot
parent beb5c85e69
commit 10d990c32c
133 changed files with 106 additions and 77 deletions

View File

@@ -0,0 +1,211 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {PersistedState, ElementMap} from './';
import {
PluginClient,
ElementSearchResultSet,
Element,
SearchInput,
SearchBox,
SearchIcon,
LoadingIndicator,
styled,
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 | null; // Not supported in iOS
};
type Props = {
client: PluginClient;
inAXMode: boolean;
onSearchResults: (searchResults: ElementSearchResultSet) => void;
setPersistedState: (state: Partial<PersistedState>) => void;
persistedState: PersistedState;
initialQuery: string | null;
};
type State = {
value: string;
outstandingSearchQuery: string | null;
};
const LoadingSpinner = styled(LoadingIndicator)({
marginRight: 4,
marginLeft: 3,
marginTop: -1,
});
export default class Search extends Component<Props, State> {
state = {
value: '',
outstandingSearchQuery: null,
};
timer: NodeJS.Timeout | undefined;
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: React.KeyboardEvent) => {
if (e.key === 'Enter') {
this.performSearch(this.state.value);
}
};
componentDidMount() {
if (this.props.initialQuery) {
const queryString = this.props.initialQuery
? this.props.initialQuery
: '';
if (this.timer) {
clearTimeout(this.timer);
}
this.timer = setTimeout(() => this.performSearch(queryString), 200);
}
}
performSearch(query: string) {
this.setState({
outstandingSearchQuery: query,
});
if (!query) {
this.displaySearchResults(
{query: '', results: null},
this.props.inAXMode,
);
} else {
this.props.client
.call('getSearchResults', {query, axEnabled: this.props.inAXMode})
.then(response =>
this.displaySearchResults(response, this.props.inAXMode),
);
}
}
displaySearchResults(
{
results,
query,
}: {
results: SearchResultTree | null;
query: string;
},
axMode: boolean,
) {
this.setState({
outstandingSearchQuery:
query === this.state.outstandingSearchQuery
? null
: this.state.outstandingSearchQuery,
});
const searchResults = this.getElementsFromSearchResultTree(results);
const searchResultIDs = new Set(searchResults.map(r => r.element.id));
const elements: ElementMap = searchResults.reduce(
(acc: ElementMap, {element}: SearchResultTree) => ({
...acc,
[element.id]: {
...element,
// expand all search results, that we have have children for
expanded: element.children.some(c => searchResultIDs.has(c)),
},
}),
this.props.persistedState.elements,
);
let {AXelements} = this.props.persistedState;
if (axMode) {
AXelements = searchResults.reduce(
(acc: ElementMap, {axElement}: SearchResultTree) => {
if (!axElement) {
return acc;
}
return {
...acc,
[axElement.id]: {
...axElement,
// expand all search results, that we have have children for
expanded: axElement.children.some(c => searchResultIDs.has(c)),
},
};
},
this.props.persistedState.AXelements,
);
}
this.props.setPersistedState({elements, AXelements});
this.props.onSearchResults({
matches: new Set(
searchResults.filter(x => x.isMatch).map(x => x.element.id),
),
query: query,
});
}
getElementsFromSearchResultTree(
tree: SearchResultTree | null,
): Array<SearchResultTree> {
if (!tree) {
return [];
}
let elements = [
{
children: [] as Array<SearchResultTree>,
id: tree.id,
isMatch: tree.isMatch,
hasChildren: Boolean(tree.children),
element: tree.element,
axElement: tree.axElement,
},
];
if (tree.children) {
for (const child of tree.children) {
elements = elements.concat(this.getElementsFromSearchResultTree(child));
}
}
return elements;
}
render() {
return (
<SearchBox tabIndex={-1}>
<SearchIcon
name="magnifying-glass"
color={colors.macOSTitleBarIcon}
size={16}
/>
<SearchInput
placeholder={'Search'}
onChange={this.onChange}
onKeyDown={this.onKeyDown}
value={this.state.value}
/>
{this.state.outstandingSearchQuery && <LoadingSpinner size={16} />}
</SearchBox>
);
}
}