Skip to content

Commit 6eb79ec

Browse files
danilsomsikovDevtools-frontend LUCI CQ
authored andcommitted
Make Toolbar recognize items provided in the HTML template, implement devtools-toolbar-input and use it in the protocol monitor.
Bug: 388730998 Change-Id: I8f28455d5245f51ca7d50df86e09da47629f3672 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6298133 Commit-Queue: Benedikt Meurer <[email protected]> Auto-Submit: Danil Somsikov <[email protected]> Reviewed-by: Benedikt Meurer <[email protected]>
1 parent 7e09dc1 commit 6eb79ec

File tree

3 files changed

+201
-77
lines changed

3 files changed

+201
-77
lines changed

front_end/panels/protocol_monitor/ProtocolMonitor.ts

Lines changed: 76 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ import * as TextUtils from '../../models/text_utils/text_utils.js';
1616
import * as Buttons from '../../ui/components/buttons/buttons.js';
1717
import * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
1818
import * as UI from '../../ui/legacy/legacy.js';
19-
import {html, render} from '../../ui/lit/lit.js';
19+
import {Directives, html, render} from '../../ui/lit/lit.js';
2020
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
2121

2222
import {type Command, Events as JSONEditorEvents, JSONEditor, type Parameter} from './JSONEditor.js';
2323
import protocolMonitorStyles from './protocolMonitor.css.js';
2424

25+
const {styleMap} = Directives;
2526
const {widgetConfig} = UI.Widget;
2627
const UIStrings = {
2728
/**
@@ -176,15 +177,21 @@ export interface ProtocolDomain {
176177
export interface ViewInput {
177178
messages: Message[];
178179
selectedMessage?: Message;
179-
filters: TextUtils.TextUtils.ParsedFilter[];
180+
hideInputBar: boolean;
181+
command: string;
182+
commandSuggestions: string[];
183+
filterKeys: string[];
184+
filter: string;
185+
parseFilter: (filter: string) => TextUtils.TextUtils.ParsedFilter[];
180186
onRecord: (e: Event) => void;
181187
onClear: () => void;
182188
onSave: () => void;
183189
onSelect: (e: CustomEvent<HTMLElement|null>) => void;
184190
onContextMenu: (e: CustomEvent<{menu: UI.ContextMenu.ContextMenu, element: HTMLElement}>) => void;
185-
textFilterUI: UI.Toolbar.ToolbarInput;
191+
onFilterChanged: (e: CustomEvent<string>) => void;
192+
onCommandChange: (e: CustomEvent<string>) => void;
193+
onCommandSubmitted: (e: CustomEvent<string>) => void;
186194
showHideSidebarButton: UI.Toolbar.ToolbarButton;
187-
commandInput: UI.Toolbar.ToolbarInput;
188195
selector: UI.Toolbar.ToolbarComboBox;
189196
}
190197

@@ -198,17 +205,17 @@ export class ProtocolMonitorDataGrid extends Common.ObjectWrapper.eventMixin<Eve
198205
private startTime: number;
199206
private readonly messageForId = new Map<number, Message>();
200207
private readonly filterParser: TextUtils.TextUtils.FilterParser;
201-
private readonly suggestionBuilder: UI.FilterSuggestionBuilder.FilterSuggestionBuilder;
202-
private readonly textFilterUI: UI.Toolbar.ToolbarInput;
208+
#filterKeys = ['method', 'request', 'response', 'target', 'session'];
203209
readonly selector: UI.Toolbar.ToolbarComboBox;
204210
#commandAutocompleteSuggestionProvider = new CommandAutocompleteSuggestionProvider();
205211
#selectedTargetId?: string;
206-
#commandInput: UI.Toolbar.ToolbarInput;
212+
#command = '';
213+
#hideInputBar = false;
207214
#showHideSidebarButton: UI.Toolbar.ToolbarButton;
208215
#view: View;
209216
#messages: Message[] = [];
210217
#selectedMessage: Message|undefined;
211-
#filters: TextUtils.TextUtils.ParsedFilter[] = [];
218+
#filter = '';
212219
#splitWidget: UI.SplitWidget.SplitWidget;
213220
constructor(splitWidget: UI.SplitWidget.SplitWidget, view: View = (input, output, target) => {
214221
// clang-format off
@@ -233,7 +240,17 @@ export class ProtocolMonitorDataGrid extends Common.ObjectWrapper.eventMixin<Eve
233240
.variant=${Buttons.Button.Variant.TOOLBAR}
234241
.jslogContext=${'protocol-monitor.save'}
235242
@click=${input.onSave}></devtools-button>
236-
${input.textFilterUI.element}
243+
<devtools-toolbar-input type="filter"
244+
list="filter-suggestions"
245+
style="flex-grow: 1"
246+
value=${input.filter}
247+
@change=${input.onFilterChanged}>
248+
<datalist id="filter-suggestions">
249+
${input.filterKeys.map(key => html`
250+
<option value=${key + ':'}></option>
251+
<option value=${'-' + key + ':'}></option>`)}
252+
</datalist>
253+
</devtools-toolbar-input>
237254
</devtools-toolbar>
238255
<devtools-split-widget .options=${{
239256
vertical: true,
@@ -245,7 +262,7 @@ export class ProtocolMonitorDataGrid extends Common.ObjectWrapper.eventMixin<Eve
245262
slot="main"
246263
@select=${input.onSelect}
247264
@contextmenu=${input.onContextMenu}
248-
.filters=${input.filters}>
265+
.filters=${input.parseFilter(input.filter)}>
249266
<table>
250267
<tr>
251268
<th id="type" sortable style="text-align: center" hideable weight="1">${i18nString(UIStrings.type)}</th>
@@ -302,7 +319,20 @@ export class ProtocolMonitorDataGrid extends Common.ObjectWrapper.eventMixin<Eve
302319
<devtools-toolbar class="protocol-monitor-bottom-toolbar"
303320
jslog=${VisualLogging.toolbar('bottom')}>
304321
${input.showHideSidebarButton.element}
305-
${input.commandInput.element}
322+
<devtools-toolbar-input id="command-input"
323+
style=${styleMap({
324+
'flex-grow': 1,
325+
display: input.hideInputBar ? 'none' : 'flex'})}
326+
value=${input.command}
327+
list="command-input-suggestions"
328+
placeholder=${i18nString(UIStrings.sendRawCDPCommand)}
329+
title=${i18nString(UIStrings.sendRawCDPCommandExplanation)}
330+
@change=${input.onCommandChange}
331+
@submit=${input.onCommandSubmitted}>
332+
<datalist id="command-input-suggestions">
333+
${input.commandSuggestions.map(c => html`<option value=${c}></option>`)}
334+
</datalist>
335+
</devtools-toolbar-input>
306336
${input.selector.element}
307337
</devtools-toolbar>`,
308338
target,
@@ -318,23 +348,13 @@ export class ProtocolMonitorDataGrid extends Common.ObjectWrapper.eventMixin<Eve
318348
this.contentElement.classList.add('protocol-monitor');
319349
this.selector = this.#createTargetSelector();
320350

321-
const keys = ['method', 'request', 'response', 'type', 'target', 'session'];
322-
this.filterParser = new TextUtils.TextUtils.FilterParser(keys);
323-
this.suggestionBuilder = new UI.FilterSuggestionBuilder.FilterSuggestionBuilder(keys);
351+
this.#filterKeys = ['method', 'request', 'response', 'type', 'target', 'session'];
352+
this.filterParser = new TextUtils.TextUtils.FilterParser(this.#filterKeys);
324353

325-
this.textFilterUI = new UI.Toolbar.ToolbarFilter(
326-
undefined, 1, .2, '', this.suggestionBuilder.completions.bind(this.suggestionBuilder), true);
327-
this.textFilterUI.addEventListener(UI.Toolbar.ToolbarInput.Event.TEXT_CHANGED, event => {
328-
const query = event.data;
329-
this.#filters = this.filterParser.parse(query);
330-
this.requestUpdate();
331-
});
332354
this.#showHideSidebarButton = splitWidget.createShowHideSidebarButton(
333355
i18nString(UIStrings.showCDPCommandEditor), i18nString(UIStrings.hideCDPCommandEditor),
334356
i18nString(UIStrings.CDPCommandEditorShown), i18nString(UIStrings.CDPCommandEditorHidden),
335357
'protocol-monitor.toggle-command-editor');
336-
this.#commandInput = this.#createCommandInput();
337-
const inputBar = this.#commandInput.element;
338358
const tabSelector = this.selector.element;
339359

340360
const populateToolbarInput = (): void => {
@@ -352,24 +372,25 @@ export class ProtocolMonitorDataGrid extends Common.ObjectWrapper.eventMixin<Eve
352372
}
353373
}
354374
if (commandJson) {
355-
this.#commandInput.setValue(commandJson);
375+
this.#command = commandJson;
376+
this.requestUpdate();
356377
}
357378
};
358379

359380
splitWidget.addEventListener(UI.SplitWidget.Events.SHOW_MODE_CHANGED, (event => {
360381
if (event.data === 'OnlyMain') {
361382
populateToolbarInput();
362-
363-
inputBar?.setAttribute('style', 'display:flex; flex-grow: 1');
383+
this.#hideInputBar = false;
364384
tabSelector?.setAttribute('style', 'display:flex');
365385
} else {
366-
const {command, parameters} = parseCommandInput(this.#commandInput.value());
386+
const {command, parameters} = parseCommandInput(this.#command);
367387
this.dispatchEventToListeners(
368388
Events.COMMAND_CHANGE,
369389
{command, parameters, targetId: this.#selectedTargetId});
370-
inputBar?.setAttribute('style', 'display:none');
390+
this.#hideInputBar = true;
371391
tabSelector?.setAttribute('style', 'display:none');
372392
}
393+
this.requestUpdate();
373394
}));
374395
this.performUpdate();
375396
}
@@ -378,7 +399,12 @@ export class ProtocolMonitorDataGrid extends Common.ObjectWrapper.eventMixin<Eve
378399
const viewInput = {
379400
messages: this.#messages,
380401
selectedMessage: this.#selectedMessage,
381-
filters: this.#filters,
402+
hideInputBar: this.#hideInputBar,
403+
command: this.#command,
404+
commandSuggestions: this.#commandAutocompleteSuggestionProvider.allSuggestions(),
405+
filterKeys: this.#filterKeys,
406+
filter: this.#filter,
407+
parseFilter: this.filterParser.parse.bind(this.filterParser),
382408
onRecord: (e: Event) => {
383409
this.setRecording((e.target as Buttons.Button.Button).toggled);
384410
},
@@ -401,9 +427,19 @@ export class ProtocolMonitorDataGrid extends Common.ObjectWrapper.eventMixin<Eve
401427
this.#populateContextMenu(e.detail.menu, message);
402428
}
403429
},
404-
textFilterUI: this.textFilterUI,
430+
onCommandChange: (e: CustomEvent<string>) => {
431+
this.#command = e.detail;
432+
},
433+
onCommandSubmitted: (e: CustomEvent<string>) => {
434+
this.#commandAutocompleteSuggestionProvider.addEntry(e.detail);
435+
const {command, parameters} = parseCommandInput(e.detail);
436+
this.onCommandSend(command, parameters, this.#selectedTargetId);
437+
},
438+
onFilterChanged: (e: CustomEvent<string>) => {
439+
this.#filter = e.detail;
440+
this.requestUpdate();
441+
},
405442
showHideSidebarButton: this.#showHideSidebarButton,
406-
commandInput: this.#commandInput,
407443
selector: this.selector,
408444
};
409445
const viewOutput = {};
@@ -434,7 +470,8 @@ export class ProtocolMonitorDataGrid extends Common.ObjectWrapper.eventMixin<Eve
434470
* current row.
435471
*/
436472
menu.editSection().appendItem(i18nString(UIStrings.filter), () => {
437-
this.textFilterUI.setValue(`method:${message.method}`, true);
473+
this.#filter = `method:${message.method}`;
474+
this.requestUpdate();
438475
}, {jslogContext: 'filter'});
439476

440477
/**
@@ -450,30 +487,6 @@ export class ProtocolMonitorDataGrid extends Common.ObjectWrapper.eventMixin<Eve
450487
}, {jslogContext: 'documentation'});
451488
}
452489

453-
#createCommandInput(): UI.Toolbar.ToolbarInput {
454-
const placeholder = i18nString(UIStrings.sendRawCDPCommand);
455-
const accessiblePlaceholder = placeholder;
456-
const growFactor = 1;
457-
const shrinkFactor = 0.2;
458-
const tooltip = i18nString(UIStrings.sendRawCDPCommandExplanation);
459-
const input = new UI.Toolbar.ToolbarInput(
460-
placeholder,
461-
accessiblePlaceholder,
462-
growFactor,
463-
shrinkFactor,
464-
tooltip,
465-
this.#commandAutocompleteSuggestionProvider.buildTextPromptCompletions,
466-
false,
467-
'command-input',
468-
);
469-
input.addEventListener(UI.Toolbar.ToolbarInput.Event.ENTER_PRESSED, () => {
470-
this.#commandAutocompleteSuggestionProvider.addEntry(input.value());
471-
const {command, parameters} = parseCommandInput(input.value());
472-
this.onCommandSend(command, parameters, this.#selectedTargetId);
473-
});
474-
return input;
475-
}
476-
477490
#createTargetSelector(): UI.Toolbar.ToolbarComboBox {
478491
const selector = new UI.Toolbar.ToolbarComboBox(() => {
479492
this.#selectedTargetId = selector.selectedOption()?.value;
@@ -631,14 +644,19 @@ export class CommandAutocompleteSuggestionProvider {
631644
}
632645
}
633646

647+
allSuggestions(): string[] {
648+
const newestToOldest = [...this.#commandHistory].reverse();
649+
newestToOldest.push(...metadataByCommand.keys());
650+
return newestToOldest;
651+
}
652+
634653
buildTextPromptCompletions =
635654
async(expression: string, prefix: string, force?: boolean): Promise<UI.SuggestBox.Suggestions> => {
636655
if (!prefix && !force && expression) {
637656
return [];
638657
}
639658

640-
const newestToOldest = [...this.#commandHistory].reverse();
641-
newestToOldest.push(...metadataByCommand.keys());
659+
const newestToOldest = this.allSuggestions();
642660
return newestToOldest.filter(cmd => cmd.startsWith(prefix)).map(text => ({
643661
text,
644662
}));

0 commit comments

Comments
 (0)