chrome-devtools-frontend 1.0.1535712 → 1.0.1536371
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/contributing/images/issues-nearestslo.png +0 -0
- package/docs/contributing/issues.md +17 -21
- package/front_end/core/common/Console.ts +1 -8
- package/front_end/core/common/ParsedURL.ts +10 -20
- package/front_end/core/common/SegmentedRange.ts +1 -2
- package/front_end/core/common/StringOutputStream.ts +1 -4
- package/front_end/core/i18n/i18nImpl.ts +0 -24
- package/front_end/core/sdk/AnimationModel.ts +1 -2
- package/front_end/core/sdk/CSSMatchedStyles.ts +2 -2
- package/front_end/core/sdk/CSSModel.ts +1 -1
- package/front_end/core/sdk/CSSProperty.ts +3 -6
- package/front_end/core/sdk/CSSStyleDeclaration.ts +4 -4
- package/front_end/core/sdk/DebuggerModel.ts +1 -2
- package/front_end/core/sdk/EnhancedTracesParser.ts +4 -0
- package/front_end/core/sdk/SourceMap.ts +2 -3
- package/front_end/entrypoints/node_app/NodeConnectionsPanel.ts +2 -1
- package/front_end/generated/InspectorBackendCommands.js +1 -2
- package/front_end/generated/SupportedCSSProperties.js +19 -0
- package/front_end/generated/protocol.ts +0 -27
- package/front_end/panels/accessibility/AccessibilityNodeView.ts +18 -17
- package/front_end/panels/accessibility/AccessibilitySidebarView.ts +9 -12
- package/front_end/panels/ai_assistance/components/ChatView.ts +5 -4
- package/front_end/panels/application/AppManifestView.ts +7 -6
- package/front_end/panels/application/ApplicationPanelSidebar.ts +4 -4
- package/front_end/panels/application/OpenedWindowDetailsView.ts +6 -6
- package/front_end/panels/application/StorageView.ts +9 -8
- package/front_end/panels/application/components/BackForwardCacheView.ts +333 -314
- package/front_end/panels/application/components/ProtocolHandlersView.ts +3 -2
- package/front_end/panels/application/preloading/components/PreloadingDisabledInfobar.ts +2 -1
- package/front_end/panels/browser_debugger/ObjectEventListenersSidebarPane.ts +8 -8
- package/front_end/panels/common/BadgeNotification.ts +2 -1
- package/front_end/panels/common/GdpSignUpDialog.ts +2 -1
- package/front_end/panels/console/ConsoleInsightTeaser.ts +8 -2
- package/front_end/panels/console/ConsolePinPane.ts +12 -7
- package/front_end/panels/developer_resources/DeveloperResourcesView.ts +9 -9
- package/front_end/panels/elements/ComputedStyleWidget.ts +7 -7
- package/front_end/panels/elements/EventListenersWidget.ts +9 -9
- package/front_end/panels/elements/NodeStackTraceWidget.ts +6 -6
- package/front_end/panels/elements/PlatformFontsWidget.ts +5 -5
- package/front_end/panels/elements/PropertiesWidget.ts +8 -8
- package/front_end/panels/layer_viewer/Layers3DView.ts +2 -1
- package/front_end/panels/layer_viewer/PaintProfilerView.ts +3 -3
- package/front_end/panels/network/RequestCookiesView.ts +2 -1
- package/front_end/panels/network/RequestTimingView.ts +2 -1
- package/front_end/panels/recorder/RecorderController.ts +34 -23
- package/front_end/panels/recorder/components/CreateRecordingView.ts +249 -240
- package/front_end/panels/security/CookieControlsView.ts +2 -1
- package/front_end/panels/security/CookieReportView.ts +3 -2
- package/front_end/panels/settings/AISettingsTab.ts +2 -1
- package/front_end/panels/settings/KeybindsSettingsTab.ts +6 -0
- package/front_end/panels/settings/components/SyncSection.ts +2 -1
- package/front_end/panels/sources/DebuggerPausedMessage.ts +4 -3
- package/front_end/panels/sources/ResourceOriginPlugin.ts +3 -2
- package/front_end/panels/sources/SourcesNavigator.ts +2 -1
- package/front_end/panels/sources/TabbedEditorContainer.ts +3 -2
- package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +9 -9
- package/front_end/panels/timeline/TimelineUIUtils.ts +3 -2
- package/front_end/panels/timeline/components/DetailsView.ts +5 -4
- package/front_end/panels/timeline/components/FieldSettingsDialog.ts +2 -1
- package/front_end/panels/timeline/components/LiveMetricsView.ts +5 -4
- package/front_end/panels/timeline/components/MetricCompareStrings.ts +25 -24
- package/front_end/panels/timeline/components/insights/LCPDiscovery.ts +2 -1
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/docs/tooltip/basic.ts +1 -1
- package/front_end/ui/components/tooltips/Tooltip.ts +32 -17
- package/front_end/ui/i18n/i18n.ts +31 -0
- package/front_end/ui/legacy/SoftDropDown.ts +1 -12
- package/front_end/ui/legacy/ViewManager.ts +2 -4
- package/front_end/ui/legacy/Widget.ts +33 -17
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +2 -1
- package/front_end/ui/legacy/legacy.ts +0 -2
- package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
- package/mcp/mcp.ts +1 -0
- package/package.json +1 -1
- package/front_end/ui/components/docs/recorder_create_recording_view/basic.html +0 -20
- package/front_end/ui/components/docs/recorder_create_recording_view/basic.ts +0 -27
- package/front_end/ui/legacy/ThrottledWidget.ts +0 -48
|
@@ -233,6 +233,7 @@ export class RecorderController extends LitElement {
|
|
|
233
233
|
'disable-self-xss-warning', false, Common.Settings.SettingStorageType.SYNCED);
|
|
234
234
|
|
|
235
235
|
#recordingView?: Components.RecordingView.RecordingView;
|
|
236
|
+
#createRecordingView?: Components.CreateRecordingView.CreateRecordingView;
|
|
236
237
|
|
|
237
238
|
constructor() {
|
|
238
239
|
super();
|
|
@@ -804,7 +805,9 @@ export class RecorderController extends LitElement {
|
|
|
804
805
|
this.#clearError();
|
|
805
806
|
}
|
|
806
807
|
|
|
807
|
-
async #onRecordingStarted(
|
|
808
|
+
async #onRecordingStarted(
|
|
809
|
+
data: {name: string, selectorTypesToRecord: Models.Schema.SelectorType[], selectorAttribute?: string}):
|
|
810
|
+
Promise<void> {
|
|
808
811
|
// Recording is not available in device mode.
|
|
809
812
|
await this.#disableDeviceModeIfEnabled();
|
|
810
813
|
|
|
@@ -815,10 +818,10 @@ export class RecorderController extends LitElement {
|
|
|
815
818
|
// -- Recording logic starts here --
|
|
816
819
|
Host.userMetrics.recordingToggled(Host.UserMetrics.RecordingToggled.RECORDING_STARTED);
|
|
817
820
|
this.currentRecordingSession = new Models.RecordingSession.RecordingSession(this.#getMainTarget(), {
|
|
818
|
-
title:
|
|
819
|
-
selectorAttribute:
|
|
820
|
-
selectorTypesToRecord:
|
|
821
|
-
|
|
821
|
+
title: data.name,
|
|
822
|
+
selectorAttribute: data.selectorAttribute,
|
|
823
|
+
selectorTypesToRecord: data.selectorTypesToRecord.length ? data.selectorTypesToRecord :
|
|
824
|
+
Object.values(Models.Schema.SelectorType),
|
|
822
825
|
});
|
|
823
826
|
this.#setCurrentRecording(await this.#storage.saveRecording(this.currentRecordingSession.cloneUserFlow()));
|
|
824
827
|
|
|
@@ -901,7 +904,7 @@ export class RecorderController extends LitElement {
|
|
|
901
904
|
this.dispatchEvent(new Events.RecordingStateChangedEvent(this.currentRecording.flow));
|
|
902
905
|
}
|
|
903
906
|
|
|
904
|
-
async
|
|
907
|
+
async onRecordingCancelled(): Promise<void> {
|
|
905
908
|
if (this.previousPage) {
|
|
906
909
|
this.#setCurrentPage(this.previousPage);
|
|
907
910
|
}
|
|
@@ -1060,15 +1063,17 @@ export class RecorderController extends LitElement {
|
|
|
1060
1063
|
|
|
1061
1064
|
case Actions.RecorderActions.START_RECORDING:
|
|
1062
1065
|
if (this.currentPage !== Pages.CREATE_RECORDING_PAGE && !this.isRecording) {
|
|
1063
|
-
this.#shortcutHelper.handleShortcut(this.#onRecordingStarted.bind(
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1066
|
+
this.#shortcutHelper.handleShortcut(this.#onRecordingStarted.bind(this, {
|
|
1067
|
+
name: this.#recorderSettings.defaultTitle,
|
|
1068
|
+
selectorTypesToRecord: this.#recorderSettings.defaultSelectors,
|
|
1069
|
+
selectorAttribute: this.#recorderSettings.selectorAttribute ? this.#recorderSettings.selectorAttribute :
|
|
1070
|
+
undefined,
|
|
1071
|
+
}));
|
|
1068
1072
|
} else if (this.currentPage === Pages.CREATE_RECORDING_PAGE) {
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1073
|
+
if (this.#createRecordingView) {
|
|
1074
|
+
this.#shortcutHelper.handleShortcut(() => {
|
|
1075
|
+
this.#createRecordingView?.triggerFormSubmission();
|
|
1076
|
+
});
|
|
1072
1077
|
}
|
|
1073
1078
|
} else if (this.isRecording) {
|
|
1074
1079
|
void this.#onRecordingFinished();
|
|
@@ -1233,15 +1238,21 @@ export class RecorderController extends LitElement {
|
|
|
1233
1238
|
#renderCreateRecordingPage(): Lit.TemplateResult {
|
|
1234
1239
|
// clang-format off
|
|
1235
1240
|
return html`
|
|
1236
|
-
<devtools-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1241
|
+
<devtools-widget
|
|
1242
|
+
class="recording-view"
|
|
1243
|
+
.widgetConfig=${UI.Widget.widgetConfig(Components.CreateRecordingView.CreateRecordingView, {
|
|
1244
|
+
recorderSettings: this.#recorderSettings,
|
|
1245
|
+
defaultRecordingName: this.#recorderSettings.defaultTitle,
|
|
1246
|
+
onRecordingStarted: this.#onRecordingStarted.bind(this),
|
|
1247
|
+
onRecordingCancelled: this.onRecordingCancelled.bind(this),
|
|
1248
|
+
})}
|
|
1249
|
+
${UI.Widget.widgetRef(
|
|
1250
|
+
Components.CreateRecordingView.CreateRecordingView,
|
|
1251
|
+
widget => {
|
|
1252
|
+
this.#createRecordingView = widget;
|
|
1253
|
+
},
|
|
1254
|
+
)}
|
|
1255
|
+
></devtools-widget>
|
|
1245
1256
|
`;
|
|
1246
1257
|
// clang-format on
|
|
1247
1258
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
// Copyright 2023 The Chromium Authors
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
|
-
/* eslint-disable @devtools/no-lit-render-outside-of-view */
|
|
5
4
|
|
|
6
|
-
import '../../../ui/legacy/legacy.js';
|
|
7
5
|
import '../../../ui/components/icon_button/icon_button.js';
|
|
8
6
|
import './ControlButton.js';
|
|
9
7
|
|
|
@@ -11,6 +9,7 @@ import * as i18n from '../../../core/i18n/i18n.js';
|
|
|
11
9
|
import * as Badges from '../../../models/badges/badges.js';
|
|
12
10
|
import * as Buttons from '../../../ui/components/buttons/buttons.js';
|
|
13
11
|
import * as Input from '../../../ui/components/input/input.js';
|
|
12
|
+
import * as UI from '../../../ui/legacy/legacy.js';
|
|
14
13
|
import * as Lit from '../../../ui/lit/lit.js';
|
|
15
14
|
import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
|
|
16
15
|
import * as Models from '../models/models.js';
|
|
@@ -18,7 +17,7 @@ import * as Actions from '../recorder-actions/recorder-actions.js';
|
|
|
18
17
|
|
|
19
18
|
import createRecordingViewStyles from './createRecordingView.css.js';
|
|
20
19
|
|
|
21
|
-
const {html, Directives: {ifDefined}} = Lit;
|
|
20
|
+
const {html, Directives: {ifDefined, ref, createRef}} = Lit;
|
|
22
21
|
|
|
23
22
|
const UIStrings = {
|
|
24
23
|
/**
|
|
@@ -103,272 +102,282 @@ const str_ = i18n.i18n.registerUIStrings(
|
|
|
103
102
|
);
|
|
104
103
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
105
104
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
105
|
+
export interface ViewInput {
|
|
106
|
+
defaultRecordingName: string;
|
|
107
|
+
recorderSettings?: Models.RecorderSettings.RecorderSettings;
|
|
108
|
+
error?: Error;
|
|
109
|
+
startRecording: (name: string, selectorTypes: Models.Schema.SelectorType[], selectorAttribute?: string) => void;
|
|
110
|
+
onRecordingCancelled: () => void;
|
|
111
|
+
resetError: () => void;
|
|
114
112
|
}
|
|
115
113
|
|
|
116
|
-
export
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
selectorAttribute?: string;
|
|
120
|
-
selectorTypesToRecord: Models.Schema.SelectorType[];
|
|
121
|
-
|
|
122
|
-
constructor(
|
|
123
|
-
name: string,
|
|
124
|
-
selectorTypesToRecord: Models.Schema.SelectorType[],
|
|
125
|
-
selectorAttribute?: string,
|
|
126
|
-
) {
|
|
127
|
-
super(RecordingStartedEvent.eventName, {});
|
|
128
|
-
this.name = name;
|
|
129
|
-
this.selectorAttribute = selectorAttribute || undefined;
|
|
130
|
-
this.selectorTypesToRecord = selectorTypesToRecord;
|
|
131
|
-
}
|
|
114
|
+
export interface ViewOutput {
|
|
115
|
+
focusInput?: () => void;
|
|
116
|
+
triggerFormSubmission?: () => void;
|
|
132
117
|
}
|
|
133
118
|
|
|
134
|
-
export
|
|
135
|
-
|
|
136
|
-
constructor() {
|
|
137
|
-
super(RecordingCancelledEvent.eventName);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
119
|
+
export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLElement): void => {
|
|
120
|
+
const {defaultRecordingName, recorderSettings, error, startRecording, onRecordingCancelled, resetError} = input;
|
|
140
121
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
122
|
+
// TODO(crbug.com/455531160): move state from input elements into the presenter widget.
|
|
123
|
+
const selectorTypeToLabel = new Map([
|
|
124
|
+
[Models.Schema.SelectorType.ARIA, i18nString(UIStrings.selectorTypeARIA)],
|
|
125
|
+
[Models.Schema.SelectorType.CSS, i18nString(UIStrings.selectorTypeCSS)],
|
|
126
|
+
[Models.Schema.SelectorType.Text, i18nString(UIStrings.selectorTypeText)],
|
|
127
|
+
[
|
|
128
|
+
Models.Schema.SelectorType.XPath,
|
|
129
|
+
i18nString(UIStrings.selectorTypeXPath),
|
|
130
|
+
],
|
|
131
|
+
[
|
|
132
|
+
Models.Schema.SelectorType.Pierce,
|
|
133
|
+
i18nString(UIStrings.selectorTypePierce),
|
|
134
|
+
],
|
|
135
|
+
]);
|
|
136
|
+
function getSelectorTypes(): Models.Schema.SelectorType[] {
|
|
137
|
+
const selectorTypeElements = target.querySelectorAll(
|
|
138
|
+
'.selector-type input[type=checkbox]',
|
|
139
|
+
);
|
|
140
|
+
const selectorTypesToRecord: Models.Schema.SelectorType[] = [];
|
|
141
|
+
for (const selectorType of selectorTypeElements) {
|
|
142
|
+
const checkbox = selectorType as HTMLInputElement;
|
|
143
|
+
const checkboxValue = checkbox.value as Models.Schema.SelectorType;
|
|
144
|
+
if (checkbox.checked) {
|
|
145
|
+
selectorTypesToRecord.push(checkboxValue);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return selectorTypesToRecord;
|
|
149
|
+
}
|
|
144
150
|
|
|
145
|
-
|
|
146
|
-
readonly #shadow = this.attachShadow({mode: 'open'});
|
|
147
|
-
#defaultRecordingName = '';
|
|
148
|
-
#error?: Error;
|
|
149
|
-
#recorderSettings?: Models.RecorderSettings.RecorderSettings;
|
|
151
|
+
const selectorAttributeInputRef = createRef<HTMLInputElement>();
|
|
150
152
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
153
|
+
function getSelectorAttribute(): string|undefined {
|
|
154
|
+
const selectorAttribute = selectorAttributeInputRef.value?.value.trim();
|
|
155
|
+
if (!selectorAttribute) {
|
|
156
|
+
return undefined;
|
|
157
|
+
}
|
|
158
|
+
return selectorAttribute;
|
|
154
159
|
}
|
|
155
160
|
|
|
156
|
-
|
|
157
|
-
this.#render();
|
|
158
|
-
this.#shadow.querySelector('input')?.focus();
|
|
159
|
-
}
|
|
161
|
+
const nameInputRef = createRef<HTMLInputElement>();
|
|
160
162
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
this.#defaultRecordingName = this.#recorderSettings.defaultTitle;
|
|
163
|
+
function handleStartRecording(): void {
|
|
164
|
+
startRecording(nameInputRef.value?.value ?? '', getSelectorTypes(), getSelectorAttribute());
|
|
164
165
|
}
|
|
165
166
|
|
|
166
|
-
|
|
167
|
-
if (
|
|
168
|
-
|
|
169
|
-
this.#render();
|
|
167
|
+
const onKeyDown = (event: KeyboardEvent): void => {
|
|
168
|
+
if (error) {
|
|
169
|
+
resetError();
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
const keyboardEvent = event;
|
|
173
173
|
if (keyboardEvent.key === 'Enter') {
|
|
174
|
-
|
|
174
|
+
handleStartRecording();
|
|
175
175
|
event.stopPropagation();
|
|
176
176
|
event.preventDefault();
|
|
177
177
|
}
|
|
178
|
-
}
|
|
178
|
+
};
|
|
179
179
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
throw new Error('input#user-flow-name not found');
|
|
184
|
-
}
|
|
185
|
-
if (!this.#recorderSettings) {
|
|
186
|
-
throw new Error('settings not set');
|
|
187
|
-
}
|
|
180
|
+
const onInputFocus = (): void => {
|
|
181
|
+
nameInputRef.value?.select();
|
|
182
|
+
};
|
|
188
183
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
184
|
+
output.focusInput = () => {
|
|
185
|
+
nameInputRef.value?.focus();
|
|
186
|
+
};
|
|
194
187
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const selectorTypesToRecord: Models.Schema.SelectorType[] = [];
|
|
199
|
-
for (const selectorType of selectorTypeElements) {
|
|
200
|
-
const checkbox = selectorType as HTMLInputElement;
|
|
201
|
-
const checkboxValue = checkbox.value as Models.Schema.SelectorType;
|
|
202
|
-
if (checkbox.checked) {
|
|
203
|
-
selectorTypesToRecord.push(checkboxValue);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
188
|
+
output.triggerFormSubmission = () => {
|
|
189
|
+
handleStartRecording();
|
|
190
|
+
};
|
|
206
191
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
192
|
+
// clang-format off
|
|
193
|
+
Lit.render(
|
|
194
|
+
html`
|
|
195
|
+
<style>${createRecordingViewStyles}</style>
|
|
196
|
+
<style>${Input.textInputStyles}</style>
|
|
197
|
+
<style>${Input.checkboxStyles}</style>
|
|
198
|
+
<div class="wrapper" jslog=${VisualLogging.section('create-recording-view')}>
|
|
199
|
+
<div class="header-wrapper">
|
|
200
|
+
<h1>${i18nString(UIStrings.createRecording)}</h1>
|
|
201
|
+
<devtools-button
|
|
202
|
+
title=${i18nString(UIStrings.cancelRecording)}
|
|
203
|
+
jslog=${VisualLogging.close().track({click: true})}
|
|
204
|
+
.data=${
|
|
205
|
+
{
|
|
206
|
+
variant: Buttons.Button.Variant.ICON,
|
|
207
|
+
size: Buttons.Button.Size.SMALL,
|
|
208
|
+
iconName: 'cross',
|
|
209
|
+
} as Buttons.Button.ButtonData
|
|
210
|
+
}
|
|
211
|
+
@click=${onRecordingCancelled}
|
|
212
|
+
></devtools-button>
|
|
213
|
+
</div>
|
|
214
|
+
<label class="row-label" for="user-flow-name">${i18nString(
|
|
215
|
+
UIStrings.recordingName,
|
|
216
|
+
)}</label>
|
|
217
|
+
<input
|
|
218
|
+
value=${defaultRecordingName}
|
|
219
|
+
@focus=${onInputFocus}
|
|
220
|
+
@keydown=${onKeyDown}
|
|
221
|
+
jslog=${VisualLogging.textField('user-flow-name').track({change: true})}
|
|
222
|
+
class="devtools-text-input"
|
|
223
|
+
id="user-flow-name"
|
|
224
|
+
${ref(nameInputRef)}
|
|
225
|
+
/>
|
|
226
|
+
<label class="row-label" for="selector-attribute">
|
|
227
|
+
<span>${i18nString(UIStrings.selectorAttribute)}</span>
|
|
228
|
+
<x-link
|
|
229
|
+
class="link" href="https://g.co/devtools/recorder#selector"
|
|
230
|
+
title=${i18nString(UIStrings.learnMore)}
|
|
231
|
+
jslog=${VisualLogging.link('recorder-selector-help').track({click: true})}>
|
|
232
|
+
<devtools-icon name="help">
|
|
233
|
+
</devtools-icon>
|
|
234
|
+
</x-link>
|
|
235
|
+
</label>
|
|
236
|
+
<input
|
|
237
|
+
value=${ifDefined(recorderSettings?.selectorAttribute)}
|
|
238
|
+
placeholder="data-testid"
|
|
239
|
+
@keydown=${onKeyDown}
|
|
240
|
+
jslog=${VisualLogging.textField('selector-attribute').track({change: true})}
|
|
241
|
+
class="devtools-text-input"
|
|
242
|
+
id="selector-attribute"
|
|
243
|
+
${ref(selectorAttributeInputRef)}
|
|
244
|
+
/>
|
|
245
|
+
<label class="row-label">
|
|
246
|
+
<span>${i18nString(UIStrings.selectorTypes)}</span>
|
|
247
|
+
<x-link
|
|
248
|
+
class="link" href="https://g.co/devtools/recorder#selector"
|
|
249
|
+
title=${i18nString(UIStrings.learnMore)}
|
|
250
|
+
jslog=${VisualLogging.link('recorder-selector-help').track({click: true})}>
|
|
251
|
+
<devtools-icon name="help">
|
|
252
|
+
</devtools-icon>
|
|
253
|
+
</x-link>
|
|
254
|
+
</label>
|
|
255
|
+
<div class="checkbox-container">
|
|
256
|
+
${Object.values(Models.Schema.SelectorType).map(selectorType => {
|
|
257
|
+
const checked =
|
|
258
|
+
recorderSettings?.getSelectorByType(selectorType);
|
|
259
|
+
return html`
|
|
260
|
+
<label class="checkbox-label selector-type">
|
|
261
|
+
<input
|
|
262
|
+
@keydown=${onKeyDown}
|
|
263
|
+
.value=${selectorType}
|
|
264
|
+
jslog=${VisualLogging.toggle().track({click: true}).context(`selector-${selectorType}`)}
|
|
265
|
+
?checked=${checked}
|
|
266
|
+
type="checkbox"
|
|
267
|
+
/>
|
|
268
|
+
${selectorTypeToLabel.get(selectorType) || selectorType}
|
|
269
|
+
</label>
|
|
270
|
+
`;
|
|
271
|
+
})}
|
|
272
|
+
</div>
|
|
214
273
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
274
|
+
${
|
|
275
|
+
error &&
|
|
276
|
+
html`
|
|
277
|
+
<div class="error" role="alert">
|
|
278
|
+
${error.message}
|
|
279
|
+
</div>
|
|
280
|
+
`
|
|
281
|
+
}
|
|
282
|
+
</div>
|
|
283
|
+
<div class="footer">
|
|
284
|
+
<div class="controls">
|
|
285
|
+
<devtools-control-button
|
|
286
|
+
@click=${handleStartRecording}
|
|
287
|
+
.label=${i18nString(UIStrings.startRecording)}
|
|
288
|
+
.shape=${'circle'}
|
|
289
|
+
jslog=${VisualLogging.action(Actions.RecorderActions.START_RECORDING).track({click: true})}
|
|
290
|
+
title=${Models.Tooltip.getTooltipForActions(
|
|
291
|
+
i18nString(UIStrings.startRecording),
|
|
292
|
+
Actions.RecorderActions.START_RECORDING,
|
|
293
|
+
)}
|
|
294
|
+
></devtools-control-button>
|
|
295
|
+
</div>
|
|
296
|
+
</div>
|
|
297
|
+
`,
|
|
298
|
+
target,
|
|
299
|
+
);
|
|
300
|
+
// clang-format on
|
|
301
|
+
};
|
|
221
302
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
303
|
+
export class CreateRecordingView extends UI.Widget.Widget {
|
|
304
|
+
#error?: Error;
|
|
305
|
+
#view: typeof DEFAULT_VIEW;
|
|
306
|
+
#output: ViewOutput = {};
|
|
307
|
+
|
|
308
|
+
onRecordingStarted:
|
|
309
|
+
(data: {name: string, selectorTypesToRecord: Models.Schema.SelectorType[], selectorAttribute?: string}) => void =
|
|
310
|
+
() => {};
|
|
311
|
+
onRecordingCancelled = (): void => {};
|
|
312
|
+
recorderSettings?: Models.RecorderSettings.RecorderSettings;
|
|
313
|
+
defaultRecordingName = '';
|
|
314
|
+
|
|
315
|
+
constructor(element?: HTMLElement, view?: typeof DEFAULT_VIEW) {
|
|
316
|
+
super(element, {useShadowDom: true});
|
|
317
|
+
this.#view = view || DEFAULT_VIEW;
|
|
236
318
|
}
|
|
237
319
|
|
|
238
|
-
|
|
239
|
-
|
|
320
|
+
override wasShown(): void {
|
|
321
|
+
super.wasShown();
|
|
322
|
+
this.requestUpdate();
|
|
323
|
+
void this.updateComplete.then(() => this.#output.focusInput?.());
|
|
240
324
|
}
|
|
241
325
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
326
|
+
triggerFormSubmission(): void {
|
|
327
|
+
this.#output.triggerFormSubmission?.();
|
|
328
|
+
}
|
|
245
329
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
{
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
jslog=${VisualLogging.link('recorder-selector-help').track({click: true})}>
|
|
299
|
-
<devtools-icon name="help">
|
|
300
|
-
</devtools-icon>
|
|
301
|
-
</x-link>
|
|
302
|
-
</label>
|
|
303
|
-
<input
|
|
304
|
-
value=${ifDefined(this.#recorderSettings?.selectorAttribute)}
|
|
305
|
-
placeholder="data-testid"
|
|
306
|
-
@keydown=${this.#onKeyDown}
|
|
307
|
-
jslog=${VisualLogging.textField('selector-attribute').track({change: true})}
|
|
308
|
-
class="devtools-text-input"
|
|
309
|
-
id="selector-attribute"
|
|
310
|
-
/>
|
|
311
|
-
<label class="row-label">
|
|
312
|
-
<span>${i18nString(UIStrings.selectorTypes)}</span>
|
|
313
|
-
<x-link
|
|
314
|
-
class="link" href="https://g.co/devtools/recorder#selector"
|
|
315
|
-
title=${i18nString(UIStrings.learnMore)}
|
|
316
|
-
jslog=${VisualLogging.link('recorder-selector-help').track({click: true})}>
|
|
317
|
-
<devtools-icon name="help">
|
|
318
|
-
</devtools-icon>
|
|
319
|
-
</x-link>
|
|
320
|
-
</label>
|
|
321
|
-
<div class="checkbox-container">
|
|
322
|
-
${Object.values(Models.Schema.SelectorType).map(selectorType => {
|
|
323
|
-
const checked =
|
|
324
|
-
this.#recorderSettings?.getSelectorByType(selectorType);
|
|
325
|
-
return html`
|
|
326
|
-
<label class="checkbox-label selector-type">
|
|
327
|
-
<input
|
|
328
|
-
@keydown=${this.#onKeyDown}
|
|
329
|
-
.value=${selectorType}
|
|
330
|
-
jslog=${VisualLogging.toggle().track({click: true}).context(`selector-${selectorType}`)}
|
|
331
|
-
?checked=${checked}
|
|
332
|
-
type="checkbox"
|
|
333
|
-
/>
|
|
334
|
-
${selectorTypeToLabel.get(selectorType) || selectorType}
|
|
335
|
-
</label>
|
|
336
|
-
`;
|
|
337
|
-
})}
|
|
338
|
-
</div>
|
|
339
|
-
|
|
340
|
-
${
|
|
341
|
-
this.#error &&
|
|
342
|
-
html`
|
|
343
|
-
<div class="error" role="alert">
|
|
344
|
-
${this.#error.message}
|
|
345
|
-
</div>
|
|
346
|
-
`
|
|
347
|
-
}
|
|
348
|
-
</div>
|
|
349
|
-
<div class="footer">
|
|
350
|
-
<div class="controls">
|
|
351
|
-
<devtools-control-button
|
|
352
|
-
@click=${this.startRecording}
|
|
353
|
-
.label=${i18nString(UIStrings.startRecording)}
|
|
354
|
-
.shape=${'circle'}
|
|
355
|
-
jslog=${VisualLogging.action(Actions.RecorderActions.START_RECORDING).track({click: true})}
|
|
356
|
-
title=${Models.Tooltip.getTooltipForActions(
|
|
357
|
-
i18nString(UIStrings.startRecording),
|
|
358
|
-
Actions.RecorderActions.START_RECORDING,
|
|
359
|
-
)}
|
|
360
|
-
></devtools-control-button>
|
|
361
|
-
</div>
|
|
362
|
-
</div>
|
|
363
|
-
`,
|
|
364
|
-
this.#shadow,
|
|
365
|
-
{ host: this },
|
|
366
|
-
);
|
|
367
|
-
// clang-format on
|
|
330
|
+
override performUpdate(): void {
|
|
331
|
+
this.#view(
|
|
332
|
+
{
|
|
333
|
+
defaultRecordingName: this.defaultRecordingName,
|
|
334
|
+
recorderSettings: this.recorderSettings,
|
|
335
|
+
error: this.#error,
|
|
336
|
+
onRecordingCancelled: this.onRecordingCancelled,
|
|
337
|
+
startRecording:
|
|
338
|
+
(name: string, selectorTypesToRecord: Models.Schema.SelectorType[], selectorAttribute?: string): void => {
|
|
339
|
+
if (!this.recorderSettings) {
|
|
340
|
+
throw new Error('settings not set');
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (!name.trim()) {
|
|
344
|
+
this.#error = new Error(i18nString(UIStrings.recordingNameIsRequired));
|
|
345
|
+
this.requestUpdate();
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (!selectorTypesToRecord.includes(Models.Schema.SelectorType.CSS) &&
|
|
350
|
+
!selectorTypesToRecord.includes(Models.Schema.SelectorType.XPath) &&
|
|
351
|
+
!selectorTypesToRecord.includes(Models.Schema.SelectorType.Pierce)) {
|
|
352
|
+
this.#error = new Error(i18nString(UIStrings.includeNecessarySelectors));
|
|
353
|
+
this.requestUpdate();
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
for (const selectorType of Object.values(Models.Schema.SelectorType)) {
|
|
358
|
+
this.recorderSettings.setSelectorByType(
|
|
359
|
+
selectorType,
|
|
360
|
+
selectorTypesToRecord.includes(selectorType),
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (selectorAttribute) {
|
|
365
|
+
this.recorderSettings.selectorAttribute = selectorAttribute;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
this.onRecordingStarted({
|
|
369
|
+
name,
|
|
370
|
+
selectorTypesToRecord,
|
|
371
|
+
selectorAttribute,
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
Badges.UserBadges.instance().recordAction(Badges.BadgeAction.RECORDER_RECORDING_STARTED);
|
|
375
|
+
},
|
|
376
|
+
resetError: () => {
|
|
377
|
+
this.#error = undefined;
|
|
378
|
+
this.requestUpdate();
|
|
379
|
+
},
|
|
380
|
+
},
|
|
381
|
+
this.#output, this.contentElement);
|
|
368
382
|
}
|
|
369
383
|
}
|
|
370
|
-
|
|
371
|
-
customElements.define(
|
|
372
|
-
'devtools-create-recording-view',
|
|
373
|
-
CreateRecordingView,
|
|
374
|
-
);
|
|
@@ -14,6 +14,7 @@ import * as Root from '../../core/root/root.js';
|
|
|
14
14
|
import * as SDK from '../../core/sdk/sdk.js';
|
|
15
15
|
import * as Buttons from '../../ui/components/buttons/buttons.js';
|
|
16
16
|
import * as Input from '../../ui/components/input/input.js';
|
|
17
|
+
import * as uiI18n from '../../ui/i18n/i18n.js';
|
|
17
18
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
18
19
|
import {Directives, html, nothing, render, type TemplateResult} from '../../ui/lit/lit.js';
|
|
19
20
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
@@ -113,7 +114,7 @@ const UIStrings = {
|
|
|
113
114
|
|
|
114
115
|
const str_ = i18n.i18n.registerUIStrings('panels/security/CookieControlsView.ts', UIStrings);
|
|
115
116
|
export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
116
|
-
export const i18nFormatString =
|
|
117
|
+
export const i18nFormatString = uiI18n.getFormatLocalizedString.bind(undefined, str_);
|
|
117
118
|
|
|
118
119
|
export interface ViewInput {
|
|
119
120
|
thirdPartyControlsDict: Root.Runtime.HostConfig['thirdPartyCookieControls'];
|