• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2020 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15import m from 'mithril';
16
17import {Disposable} from '../base/disposable';
18import {SimpleResizeObserver} from '../base/resize_observer';
19import {undoCommonChatAppReplacements} from '../base/string_utils';
20import {QueryResponse, runQuery} from '../common/queries';
21import {raf} from '../core/raf_scheduler';
22import {Engine} from '../trace_processor/engine';
23import {Callout} from '../widgets/callout';
24import {Editor} from '../widgets/editor';
25
26import {globals} from './globals';
27import {createPage} from './pages';
28import {QueryHistoryComponent, queryHistoryStorage} from './query_history';
29import {addQueryResultsTab} from './query_result_tab';
30import {QueryTable} from './query_table';
31
32interface QueryPageState {
33  enteredText: string;
34  executedQuery?: string;
35  queryResult?: QueryResponse;
36  heightPx: string;
37  generation: number;
38}
39
40const state: QueryPageState = {
41  enteredText: '',
42  heightPx: '100px',
43  generation: 0,
44};
45
46function runManualQuery(query: string) {
47  state.executedQuery = query;
48  state.queryResult = undefined;
49  const engine = getEngine();
50  if (engine) {
51    runQuery(undoCommonChatAppReplacements(query), engine).then(
52      (resp: QueryResponse) => {
53        addQueryResultsTab(
54          {
55            query: query,
56            title: 'Standalone Query',
57            prefetchedResponse: resp,
58          },
59          'analyze_page_query',
60        );
61        // We might have started to execute another query. Ignore it in that
62        // case.
63        if (state.executedQuery !== query) {
64          return;
65        }
66        state.queryResult = resp;
67        raf.scheduleFullRedraw();
68      },
69    );
70  }
71  raf.scheduleDelayedFullRedraw();
72}
73
74function getEngine(): Engine | undefined {
75  const engineId = globals.getCurrentEngine()?.id;
76  if (engineId === undefined) {
77    return undefined;
78  }
79  const engine = globals.engines.get(engineId)?.getProxy('QueryPage');
80  return engine;
81}
82
83class QueryInput implements m.ClassComponent {
84  private resize?: Disposable;
85
86  oncreate({dom}: m.CVnodeDOM): void {
87    this.resize = new SimpleResizeObserver(dom, () => {
88      state.heightPx = (dom as HTMLElement).style.height;
89    });
90    (dom as HTMLElement).style.height = state.heightPx;
91  }
92
93  onremove(): void {
94    if (this.resize) {
95      this.resize.dispose();
96      this.resize = undefined;
97    }
98  }
99
100  view() {
101    return m(Editor, {
102      generation: state.generation,
103      initialText: state.enteredText,
104
105      onExecute: (text: string) => {
106        if (!text) {
107          return;
108        }
109        queryHistoryStorage.saveQuery(text);
110        runManualQuery(text);
111      },
112
113      onUpdate: (text: string) => {
114        state.enteredText = text;
115      },
116    });
117  }
118}
119
120export const QueryPage = createPage({
121  view() {
122    return m(
123      '.query-page',
124      m(Callout, 'Enter query and press Cmd/Ctrl + Enter'),
125      m(QueryInput),
126      state.executedQuery === undefined
127        ? null
128        : m(QueryTable, {
129            query: state.executedQuery,
130            resp: state.queryResult,
131            fillParent: false,
132          }),
133      m(QueryHistoryComponent, {
134        runQuery: runManualQuery,
135        setQuery: (q: string) => {
136          state.enteredText = q;
137          state.generation++;
138          raf.scheduleFullRedraw();
139        },
140      }),
141    );
142  },
143});
144