chrome-devtools-frontend 1.0.1558690 → 1.0.1561080

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.
Files changed (167) hide show
  1. package/front_end/Images/src/container.svg +4 -0
  2. package/front_end/core/common/Gzip.ts +15 -0
  3. package/front_end/core/host/InspectorFrontendHostStub.ts +0 -3
  4. package/front_end/core/platform/ArrayUtilities.ts +13 -0
  5. package/front_end/core/root/Runtime.ts +0 -5
  6. package/front_end/core/sdk/CSSMetadata.ts +6 -6
  7. package/front_end/core/sdk/CSSModel.ts +2 -2
  8. package/front_end/core/sdk/DOMModel.ts +15 -3
  9. package/front_end/core/sdk/NetworkManager.ts +4 -0
  10. package/front_end/core/sdk/NetworkRequest.ts +9 -0
  11. package/front_end/core/sdk/OverlayModel.ts +20 -9
  12. package/front_end/entrypoints/main/MainImpl.ts +2 -1
  13. package/front_end/generated/InspectorBackendCommands.ts +6 -3
  14. package/front_end/generated/SupportedCSSProperties.js +64 -32
  15. package/front_end/generated/protocol-mapping.d.ts +16 -0
  16. package/front_end/generated/protocol-proxy-api.d.ts +12 -0
  17. package/front_end/generated/protocol.ts +38 -1
  18. package/front_end/models/ai_assistance/agents/StylingAgent.ts +1 -1
  19. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +11 -7
  20. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +23 -22
  21. package/front_end/models/badges/UserBadges.ts +48 -16
  22. package/front_end/models/greendev/Prototypes.ts +6 -1
  23. package/front_end/models/trace/LanternComputationData.ts +4 -3
  24. package/front_end/models/trace/Processor.ts +6 -5
  25. package/front_end/models/trace/Styles.ts +10 -1
  26. package/front_end/models/trace/extras/TraceTree.ts +1 -1
  27. package/front_end/models/trace/handlers/LargestImagePaintHandler.ts +2 -2
  28. package/front_end/models/trace/handlers/MetaHandler.ts +14 -0
  29. package/front_end/models/trace/handlers/PageLoadMetricsHandler.ts +59 -34
  30. package/front_end/models/trace/helpers/Timing.ts +8 -1
  31. package/front_end/models/trace/insights/Common.ts +1 -1
  32. package/front_end/models/trace/insights/LCPBreakdown.ts +4 -4
  33. package/front_end/models/trace/insights/LCPDiscovery.ts +3 -3
  34. package/front_end/models/trace/insights/RenderBlocking.ts +1 -1
  35. package/front_end/models/trace/insights/types.ts +1 -1
  36. package/front_end/models/trace/types/TraceEvents.ts +62 -10
  37. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +11 -142
  38. package/front_end/panels/ai_assistance/PatchWidget.ts +90 -72
  39. package/front_end/panels/ai_assistance/ai_assistance.ts +1 -0
  40. package/front_end/panels/ai_assistance/components/ChatInput.ts +701 -0
  41. package/front_end/panels/ai_assistance/components/ChatView.ts +71 -1268
  42. package/front_end/panels/ai_assistance/components/UserActionRow.ts +514 -31
  43. package/front_end/panels/ai_assistance/components/chatInput.css +387 -0
  44. package/front_end/panels/ai_assistance/components/chatView.css +38 -599
  45. package/front_end/panels/ai_assistance/components/userActionRow.css +230 -0
  46. package/front_end/panels/autofill/AutofillView.ts +2 -2
  47. package/front_end/panels/changes/ChangesView.ts +15 -1
  48. package/front_end/panels/changes/changesView.css +6 -0
  49. package/front_end/panels/common/AiCodeGenerationTeaser.ts +48 -12
  50. package/front_end/panels/common/BadgeNotification.ts +44 -58
  51. package/front_end/panels/common/CopyChangesToPrompt.ts +233 -0
  52. package/front_end/panels/common/aiCodeGenerationTeaser.css +14 -0
  53. package/front_end/panels/common/common.ts +2 -1
  54. package/front_end/panels/console/consoleView.css +1 -1
  55. package/front_end/panels/elements/CSSRuleValidator.ts +38 -0
  56. package/front_end/panels/elements/ElementsTreeElement.ts +222 -377
  57. package/front_end/panels/elements/ElementsTreeOutline.ts +0 -23
  58. package/front_end/panels/elements/ShortcutTreeElement.ts +57 -50
  59. package/front_end/panels/elements/StylePropertiesSection.ts +1 -3
  60. package/front_end/panels/elements/StylesSidebarPane.ts +15 -4
  61. package/front_end/panels/elements/components/AdornerManager.ts +5 -149
  62. package/front_end/panels/issues/HiddenIssuesRow.ts +1 -2
  63. package/front_end/panels/issues/IssueKindView.ts +2 -4
  64. package/front_end/panels/issues/IssueView.ts +2 -4
  65. package/front_end/panels/network/NetworkDataGridNode.ts +65 -1
  66. package/front_end/panels/network/NetworkLogView.ts +2 -4
  67. package/front_end/panels/network/NetworkLogViewColumns.ts +9 -0
  68. package/front_end/panels/screencast/ScreencastApp.ts +1 -0
  69. package/front_end/panels/settings/SettingsScreen.ts +3 -2
  70. package/front_end/panels/timeline/CompatibilityTracksAppender.ts +14 -1
  71. package/front_end/panels/timeline/StatusDialog.ts +4 -3
  72. package/front_end/panels/timeline/ThirdPartyTreeView.ts +1 -4
  73. package/front_end/panels/timeline/TimelineController.ts +185 -3
  74. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +52 -25
  75. package/front_end/panels/timeline/TimelineFlameChartNetworkDataProvider.ts +3 -16
  76. package/front_end/panels/timeline/TimelineFlameChartView.ts +65 -21
  77. package/front_end/panels/timeline/TimelinePanel.ts +86 -126
  78. package/front_end/panels/timeline/TimelineTreeView.ts +1 -0
  79. package/front_end/panels/timeline/TimelineUIUtils.ts +28 -2
  80. package/front_end/panels/timeline/TimingsTrackAppender.ts +3 -1
  81. package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +1 -1
  82. package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +2 -2
  83. package/front_end/panels/timeline/components/insights/RenderBlocking.ts +6 -4
  84. package/front_end/panels/timeline/components/insights/Table.ts +3 -3
  85. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +4 -0
  86. package/front_end/panels/timeline/timelinePanel.css +8 -1
  87. package/front_end/panels/timeline/utils/EntryNodes.ts +2 -1
  88. package/front_end/panels/whats_new/ReleaseNoteText.ts +15 -9
  89. package/front_end/panels/whats_new/resources/WNDT.md +6 -6
  90. package/front_end/third_party/chromium/README.chromium +1 -1
  91. package/front_end/third_party/codemirror.next/rebuild.sh +1 -1
  92. package/front_end/third_party/lit/rebuild.sh +1 -1
  93. package/front_end/third_party/puppeteer/README.chromium +2 -2
  94. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts +2 -3
  95. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts.map +1 -1
  96. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js.map +1 -1
  97. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.d.ts.map +1 -1
  98. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.js +9 -0
  99. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.js.map +1 -1
  100. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPResponse.d.ts +3 -0
  101. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPResponse.d.ts.map +1 -1
  102. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPResponse.js +9 -0
  103. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPResponse.js.map +1 -1
  104. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Request.d.ts +3 -0
  105. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Request.d.ts.map +1 -1
  106. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Request.js +10 -0
  107. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Request.js.map +1 -1
  108. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.d.ts.map +1 -1
  109. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js +8 -4
  110. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js.map +1 -1
  111. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.d.ts +1 -1
  112. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.d.ts.map +1 -1
  113. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.js +1 -1
  114. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.js.map +1 -1
  115. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  116. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
  117. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
  118. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
  119. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  120. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
  121. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
  122. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +10 -1
  123. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +13 -7
  124. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts +2 -3
  125. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts.map +1 -1
  126. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js.map +1 -1
  127. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.d.ts.map +1 -1
  128. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.js +9 -0
  129. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.js.map +1 -1
  130. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPResponse.d.ts +3 -0
  131. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPResponse.d.ts.map +1 -1
  132. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPResponse.js +9 -0
  133. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPResponse.js.map +1 -1
  134. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Request.d.ts +3 -0
  135. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Request.d.ts.map +1 -1
  136. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Request.js +10 -0
  137. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Request.js.map +1 -1
  138. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.d.ts.map +1 -1
  139. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js +8 -4
  140. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js.map +1 -1
  141. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.d.ts +1 -1
  142. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.d.ts.map +1 -1
  143. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.js +1 -1
  144. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.js.map +1 -1
  145. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
  146. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
  147. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
  148. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
  149. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
  150. package/front_end/third_party/puppeteer/package/lib/types.d.ts +10 -1
  151. package/front_end/third_party/puppeteer/package/package.json +3 -3
  152. package/front_end/third_party/puppeteer/package/src/api/Page.ts +2 -3
  153. package/front_end/third_party/puppeteer/package/src/bidi/HTTPRequest.ts +13 -0
  154. package/front_end/third_party/puppeteer/package/src/bidi/HTTPResponse.ts +10 -0
  155. package/front_end/third_party/puppeteer/package/src/bidi/core/Request.ts +15 -0
  156. package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +9 -4
  157. package/front_end/third_party/puppeteer/package/src/generated/injected.ts +1 -1
  158. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  159. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  160. package/front_end/ui/components/adorners/Adorner.ts +8 -68
  161. package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +70 -28
  162. package/front_end/ui/legacy/SearchableView.ts +11 -5
  163. package/front_end/ui/legacy/SplitWidget.ts +1 -1
  164. package/front_end/ui/legacy/TabbedPane.ts +1 -1
  165. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +43 -9
  166. package/front_end/ui/visual_logging/KnownContextValues.ts +16 -0
  167. package/package.json +2 -1
@@ -118,4 +118,234 @@
118
118
  padding: 0 var(--sys-size-4);
119
119
  }
120
120
  }
121
+
122
+ .chat-message {
123
+ user-select: text;
124
+ cursor: initial;
125
+ display: flex;
126
+ flex-direction: column;
127
+ gap: var(--sys-size-5);
128
+ width: 100%;
129
+ padding: var(--sys-size-7) var(--sys-size-5);
130
+ font-size: 12px;
131
+ word-break: normal;
132
+ overflow-wrap: anywhere;
133
+ border-bottom: var(--sys-size-1) solid var(--sys-color-divider);
134
+
135
+ &.is-last-message {
136
+ border-bottom: 0;
137
+ }
138
+
139
+ .message-info {
140
+ display: flex;
141
+ align-items: center;
142
+ height: var(--sys-size-11);
143
+ gap: var(--sys-size-4);
144
+ font: var(--sys-typescale-body4-bold);
145
+
146
+ img {
147
+ border: 0;
148
+ border-radius: var(--sys-shape-corner-full);
149
+ display: block;
150
+ height: var(--sys-size-9);
151
+ width: var(--sys-size-9);
152
+ }
153
+
154
+ h2 {
155
+ font: var(--sys-typescale-body4-bold);
156
+ }
157
+ }
158
+
159
+ .actions {
160
+ display: flex;
161
+ flex-direction: column;
162
+ gap: var(--sys-size-8);
163
+ max-width: 100%;
164
+ }
165
+
166
+ .aborted {
167
+ color: var(--sys-color-on-surface-subtle);
168
+ }
169
+
170
+ .image-link {
171
+ width: fit-content;
172
+ border-radius: var(--sys-shape-corner-small);
173
+ outline-offset: var(--sys-size-2);
174
+
175
+ img {
176
+ max-height: var(--sys-size-20);
177
+ max-width: 100%;
178
+ border-radius: var(--sys-shape-corner-small);
179
+ border: 1px solid var(--sys-color-neutral-outline);
180
+ width: fit-content;
181
+ vertical-align: bottom;
182
+ }
183
+ }
184
+
185
+ .unavailable-image {
186
+ margin: var(--sys-size-4) 0;
187
+ display: inline-flex;
188
+ justify-content: center;
189
+ align-items: center;
190
+ height: var(--sys-size-17);
191
+ width: var(--sys-size-18);
192
+ background-color: var(--sys-color-surface3);
193
+ border-radius: var(--sys-shape-corner-small);
194
+ border: 1px solid var(--sys-color-neutral-outline);
195
+
196
+ devtools-icon {
197
+ color: var(--sys-color-state-disabled);
198
+ }
199
+ }
200
+ }
201
+
202
+ .indicator {
203
+ color: var(--sys-color-green-bright);
204
+ }
205
+
206
+ .summary {
207
+ display: grid;
208
+ grid-template-columns: auto 1fr auto;
209
+ padding: var(--sys-size-3);
210
+ line-height: var(--sys-size-9);
211
+ cursor: default;
212
+ gap: var(--sys-size-3);
213
+ justify-content: center;
214
+ align-items: center;
215
+
216
+ .title {
217
+ text-overflow: ellipsis;
218
+ white-space: nowrap;
219
+ overflow: hidden;
220
+ font: var(--sys-typescale-body4-regular);
221
+
222
+ .paused {
223
+ font: var(--sys-typescale-body4-bold);
224
+ }
225
+ }
226
+ }
227
+
228
+ .step-code {
229
+ display: flex;
230
+ flex-direction: column;
231
+ gap: var(--sys-size-2);
232
+ }
233
+
234
+ .js-code-output {
235
+ devtools-code-block {
236
+ --code-block-max-code-height: 50px;
237
+ }
238
+ }
239
+
240
+ .context-details {
241
+ devtools-code-block {
242
+ --code-block-max-code-height: 80px;
243
+ }
244
+ }
245
+
246
+ .step {
247
+ width: fit-content;
248
+ background-color: var(--sys-color-surface3);
249
+ border-radius: var(--sys-size-6);
250
+ position: relative;
251
+
252
+ &.empty {
253
+ pointer-events: none;
254
+
255
+ .arrow {
256
+ display: none;
257
+ }
258
+ }
259
+
260
+ &:not(&[open]):hover::after {
261
+ content: '';
262
+ height: 100%;
263
+ width: 100%;
264
+ border-radius: inherit;
265
+ position: absolute;
266
+ top: 0;
267
+ left: 0;
268
+ pointer-events: none;
269
+ background-color: var(--sys-color-state-hover-on-subtle);
270
+ }
271
+
272
+ &.paused {
273
+ .indicator {
274
+ color: var(--sys-color-on-surface-subtle);
275
+ }
276
+ }
277
+
278
+ &.canceled {
279
+ .summary {
280
+ color: var(--sys-color-state-disabled);
281
+ text-decoration: line-through;
282
+ }
283
+
284
+ .indicator {
285
+ color: var(--sys-color-state-disabled);
286
+ }
287
+ }
288
+
289
+ devtools-markdown-view {
290
+ --code-background-color: var(--sys-color-surface1);
291
+ }
292
+
293
+ devtools-icon {
294
+ vertical-align: bottom;
295
+ }
296
+
297
+ devtools-spinner {
298
+ width: var(--sys-size-9);
299
+ height: var(--sys-size-9);
300
+ padding: var(--sys-size-2);
301
+ }
302
+
303
+ &[open] {
304
+ width: auto;
305
+
306
+ .summary .title {
307
+ white-space: normal;
308
+ overflow: unset;
309
+ }
310
+
311
+ .summary .arrow {
312
+ transform: rotate(180deg);
313
+ }
314
+ }
315
+
316
+ summary::marker {
317
+ content: '';
318
+ }
319
+
320
+ summary {
321
+ border-radius: var(--sys-size-6);
322
+ }
323
+
324
+ .step-details {
325
+ padding: 0 var(--sys-size-5) var(--sys-size-4) var(--sys-size-12);
326
+ display: flex;
327
+ flex-direction: column;
328
+ gap: var(--sys-size-6);
329
+
330
+ devtools-code-block {
331
+ --code-block-background-color: var(--sys-color-surface1);
332
+ }
333
+ }
334
+ }
335
+
336
+ .error-step {
337
+ color: var(--sys-color-error);
338
+ }
339
+
340
+ .side-effect-confirmation {
341
+ display: flex;
342
+ flex-direction: column;
343
+ gap: var(--sys-size-5);
344
+ padding-bottom: var(--sys-size-4);
345
+ }
346
+
347
+ .side-effect-buttons-container {
348
+ display: flex;
349
+ gap: var(--sys-size-4);
350
+ }
121
351
  }
@@ -198,11 +198,11 @@ const DEFAULT_VIEW: View = (input: ViewInput, _output: ViewOutput, target: HTMLE
198
198
  <td>
199
199
  ${field.autofillType}
200
200
  ${field.fillingStrategy === FillingStrategy.AutocompleteAttribute ?
201
- html`<devtools-adorner title=${i18nString(UIStrings.autocompleteAttribute)} .data=${{name: field.fillingStrategy}}>
201
+ html`<devtools-adorner .name=${field.fillingStrategy} title=${i18nString(UIStrings.autocompleteAttribute)}>
202
202
  <span>${i18nString(UIStrings.attr)}</span>
203
203
  </devtools-adorner>` :
204
204
  field.fillingStrategy === FillingStrategy.AutofillInferred ?
205
- html`<devtools-adorner title=${i18nString(UIStrings.inferredByHeuristics)} .data=${{name: field.fillingStrategy}}>
205
+ html`<devtools-adorner .name=${field.fillingStrategy} title=${i18nString(UIStrings.inferredByHeuristics)}>
206
206
  <span>${i18nString(UIStrings.heur)}</span>
207
207
  </devtools-adorner>` :
208
208
  Lit.nothing}
@@ -6,11 +6,13 @@ import '../../ui/legacy/legacy.js';
6
6
 
7
7
  import * as i18n from '../../core/i18n/i18n.js';
8
8
  import type * as Platform from '../../core/platform/platform.js';
9
+ import * as GreenDev from '../../models/greendev/greendev.js';
9
10
  import type * as Workspace from '../../models/workspace/workspace.js';
10
11
  import * as WorkspaceDiff from '../../models/workspace_diff/workspace_diff.js';
11
12
  import * as UI from '../../ui/legacy/legacy.js';
12
13
  import * as Lit from '../../ui/lit/lit.js';
13
14
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
15
+ import * as PanelsCommon from '../common/common.js';
14
16
 
15
17
  import {ChangesSidebar, Events} from './ChangesSidebar.js';
16
18
  import changesViewStyles from './changesView.css.js';
@@ -27,6 +29,7 @@ const UIStrings = {
27
29
  * @description Text in Changes View of the Changes tab to explain the Changes panel.
28
30
  */
29
31
  changesViewDescription: 'On this page you can track code changes made within DevTools.',
32
+
30
33
  } as const;
31
34
  const str_ = i18n.i18n.registerUIStrings('panels/changes/ChangesView.ts', UIStrings);
32
35
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -37,11 +40,14 @@ interface ViewInput {
37
40
  workspaceDiff: WorkspaceDiff.WorkspaceDiff.WorkspaceDiffImpl;
38
41
  }
39
42
  type View = (input: ViewInput, output: object, target: HTMLElement) => void;
40
- export const DEFAULT_VIEW: View = (input, output, target) => {
43
+ export const DEFAULT_VIEW: View = (input, _output, target) => {
41
44
  const onSidebar = (sidebar: ChangesSidebar): void => {
42
45
  sidebar.addEventListener(
43
46
  Events.SELECTED_UI_SOURCE_CODE_CHANGED, () => input.onSelect(sidebar.selectedUISourceCode()));
44
47
  };
48
+
49
+ const hasCopyToPrompt = GreenDev.Prototypes.instance().isEnabled('copyToGemini');
50
+
45
51
  render(
46
52
  // clang-format off
47
53
  html`
@@ -62,6 +68,14 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
62
68
  workspaceDiff: input.workspaceDiff
63
69
  })}></devtools-widget>
64
70
  </div>
71
+ ${hasCopyToPrompt ? html`
72
+ <devtools-widget class="copy-to-prompt"
73
+ .widgetConfig=${UI.Widget.widgetConfig(PanelsCommon.CopyChangesToPrompt, {
74
+ workspaceDiff: input.workspaceDiff,
75
+ patchAgentCSSChange: null,
76
+ })}
77
+ ></devtools-widget>
78
+ ` : Lit.nothing}
65
79
  </div>
66
80
  <devtools-widget
67
81
  slot="sidebar"
@@ -40,3 +40,9 @@
40
40
  [hidden] {
41
41
  display: none !important; /* stylelint-disable-line declaration-no-important */
42
42
  }
43
+
44
+ .copy-to-prompt {
45
+ margin: var(--sys-size-4);
46
+ /* Got to override the default flex properties for widgets */
47
+ flex-grow: 0 !important; /* stylelint-disable-line declaration-no-important */
48
+ }
@@ -5,7 +5,9 @@
5
5
  import * as Host from '../../core/host/host.js';
6
6
  import * as i18n from '../../core/i18n/i18n.js';
7
7
  import * as UI from '../../ui/legacy/legacy.js';
8
- import {html, render} from '../../ui/lit/lit.js';
8
+ import {html, nothing, render} from '../../ui/lit/lit.js';
9
+
10
+ import styles from './aiCodeGenerationTeaser.css.js';
9
11
 
10
12
  const UIStringsNotTranslate = {
11
13
  /**
@@ -20,23 +22,56 @@ const UIStringsNotTranslate = {
20
22
  * Text for teaser when generating suggestion.
21
23
  */
22
24
  generating: 'Generating... (esc to cancel)',
25
+ /**
26
+ * Text for teaser for discoverability.
27
+ */
28
+ writeACommentToGenerateCode: 'Write a comment to generate code',
23
29
  } as const;
24
30
 
25
31
  const lockedString = i18n.i18n.lockedString;
32
+ const PROMOTION_ID = 'ai-code-generation';
33
+
34
+ export enum AiCodeGenerationTeaserDisplayState {
35
+ TRIGGER = 'trigger',
36
+ DISCOVERY = 'discovery',
37
+ LOADING = 'loading',
38
+ }
26
39
 
27
40
  export interface ViewInput {
28
- loading: boolean;
41
+ displayState: AiCodeGenerationTeaserDisplayState;
29
42
  }
30
43
 
31
44
  export type View = (input: ViewInput, output: object, target: HTMLElement) => void;
32
45
 
33
46
  export const DEFAULT_VIEW: View = (input, _output, target) => {
34
- const toGenerateCode = Host.Platform.isMac() ? lockedString(UIStringsNotTranslate.cmdItoGenerateCode) :
35
- lockedString(UIStringsNotTranslate.ctrlItoGenerateCode);
36
- const teaserLabel = input.loading ? lockedString(UIStringsNotTranslate.generating) : toGenerateCode;
47
+ let teaserLabel;
48
+ switch (input.displayState) {
49
+ case AiCodeGenerationTeaserDisplayState.DISCOVERY: {
50
+ const newBadge = UI.UIUtils.maybeCreateNewBadge(PROMOTION_ID);
51
+ teaserLabel = newBadge ?
52
+ html`${lockedString(UIStringsNotTranslate.writeACommentToGenerateCode)}&nbsp;${newBadge}` :
53
+ nothing;
54
+ break;
55
+ }
56
+
57
+ case AiCodeGenerationTeaserDisplayState.LOADING: {
58
+ teaserLabel = html`${lockedString(UIStringsNotTranslate.generating)}`;
59
+ break;
60
+ }
61
+
62
+ case AiCodeGenerationTeaserDisplayState.TRIGGER: {
63
+ const toGenerateCode = Host.Platform.isMac() ? lockedString(UIStringsNotTranslate.cmdItoGenerateCode) :
64
+ lockedString(UIStringsNotTranslate.ctrlItoGenerateCode);
65
+ teaserLabel = html`${toGenerateCode}`;
66
+ break;
67
+ }
68
+ }
69
+
37
70
  // clang-format off
38
71
  render(
39
72
  html`
73
+ <style>${styles}</style>
74
+ <style>@scope to (devtools-widget > *) { ${UI.inspectorCommonStyles} }</style>
40
75
  <div class="ai-code-generation-teaser">
41
76
  &nbsp;${teaserLabel}
42
77
  </div>
@@ -45,10 +80,11 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
45
80
  // clang-format on
46
81
  };
47
82
 
83
+ // TODO(b/448063927): Add "Dont show again" for discovery teaser.
48
84
  export class AiCodeGenerationTeaser extends UI.Widget.Widget {
49
85
  readonly #view: View;
50
86
 
51
- #loading = false;
87
+ #displayState = AiCodeGenerationTeaserDisplayState.TRIGGER;
52
88
 
53
89
  constructor(view?: View) {
54
90
  super();
@@ -61,20 +97,20 @@ export class AiCodeGenerationTeaser extends UI.Widget.Widget {
61
97
  const output = {};
62
98
  this.#view(
63
99
  {
64
- loading: this.#loading,
100
+ displayState: this.#displayState,
65
101
  },
66
102
  output, this.contentElement);
67
103
  }
68
104
 
69
- get loading(): boolean {
70
- return this.#loading;
105
+ get displayState(): AiCodeGenerationTeaserDisplayState {
106
+ return this.#displayState;
71
107
  }
72
108
 
73
- set loading(loading: boolean) {
74
- if (loading === this.#loading) {
109
+ set displayState(displayState: AiCodeGenerationTeaserDisplayState) {
110
+ if (displayState === this.#displayState) {
75
111
  return;
76
112
  }
77
- this.#loading = loading;
113
+ this.#displayState = displayState;
78
114
  this.requestUpdate();
79
115
  }
80
116
  }
@@ -50,9 +50,9 @@ const UIStrings = {
50
50
  starterBadgeAwardMessageNoGdpProfile:
51
51
  'You earned the {PH1} badge for the {PH2}! Create a profile to claim your badge.',
52
52
  /**
53
- * @description Action title for snoozing the starter badge.
53
+ * @description Action title for dismissing the badge notification.
54
54
  */
55
- remindMeLater: 'Remind me later',
55
+ noThanks: 'No thanks',
56
56
  /**
57
57
  * @description Action title for enabling the "Receive badges" setting
58
58
  */
@@ -157,11 +157,17 @@ export class BadgeNotification extends UI.Widget.Widget {
157
157
  this.markAsRoot();
158
158
  }
159
159
 
160
- async present(badge: Badges.Badge): Promise<void> {
161
- if (badge.isStarterBadge) {
162
- await this.#presentStarterBadge(badge);
163
- } else {
164
- this.#presentActivityBasedBadge(badge);
160
+ async present(badge: Badges.Badge, reason: Badges.BadgeTriggerReason): Promise<void> {
161
+ switch (reason) {
162
+ case Badges.BadgeTriggerReason.AWARD:
163
+ this.#presentActivityBasedBadge(badge);
164
+ return;
165
+ case Badges.BadgeTriggerReason.STARTER_BADGE_SETTINGS_NUDGE:
166
+ this.#presentStarterBadgeSettingsNudge(badge);
167
+ return;
168
+ case Badges.BadgeTriggerReason.STARTER_BADGE_PROFILE_NUDGE:
169
+ this.#presentStarterBadgeProfileNudge(badge);
170
+ return;
165
171
  }
166
172
  }
167
173
 
@@ -191,70 +197,50 @@ export class BadgeNotification extends UI.Widget.Widget {
191
197
  this.#autoCloseTimeout = window.setTimeout(this.#onAutoClose, AUTO_CLOSE_TIME_IN_MS);
192
198
  }
193
199
 
194
- async #presentStarterBadge(badge: Badges.Badge): Promise<void> {
195
- const getProfileResponse = await Host.GdpClient.GdpClient.instance().getProfile();
196
- // The `getProfile` call failed and returned a `null`.
197
- // For that case, we don't show anything.
198
- if (!getProfileResponse) {
199
- return;
200
- }
201
-
202
- const hasGdpProfile = Boolean(getProfileResponse.profile);
203
- const receiveBadgesSettingEnabled = Badges.UserBadges.instance().isReceiveBadgesSettingEnabled();
200
+ #presentStarterBadgeSettingsNudge(badge: Badges.Badge): void {
204
201
  const googleDeveloperProgramLink = UI.XLink.XLink.create(
205
202
  'https://developers.google.com/program', lockedString('Google Developer Program'), 'badge-link', undefined,
206
203
  'program-link');
207
-
208
- // If the user already has a GDP profile and the receive badges setting enabled,
209
- // starter badge behaves as if it's an activity based badge.
210
- if (hasGdpProfile && receiveBadgesSettingEnabled) {
211
- this.#presentActivityBasedBadge(badge);
212
- return;
213
- }
214
-
215
- // If the user already has a GDP profile and the receive badges setting disabled,
216
- // starter badge behaves as a nudge for opting into receiving badges.
217
- if (hasGdpProfile && !receiveBadgesSettingEnabled) {
218
- this.#show({
219
- message: i18nFormatString(
220
- UIStrings.starterBadgeAwardMessageSettingDisabled, {PH1: badge.title, PH2: googleDeveloperProgramLink}),
221
- jslogContext: badge.jslogContext,
222
- actions: [
223
- {
224
- label: i18nString(UIStrings.remindMeLater),
225
- jslogContext: 'remind-me-later',
226
- onClick: () => {
227
- this.detach();
228
- Badges.UserBadges.instance().snoozeStarterBadge();
229
- },
204
+ this.#show({
205
+ message: i18nFormatString(
206
+ UIStrings.starterBadgeAwardMessageSettingDisabled, {PH1: badge.title, PH2: googleDeveloperProgramLink}),
207
+ jslogContext: badge.jslogContext,
208
+ actions: [
209
+ {
210
+ label: i18nString(UIStrings.noThanks),
211
+ jslogContext: 'no-thanks',
212
+ onClick: () => {
213
+ this.#onDismissClick();
230
214
  },
231
- {
232
- label: i18nString(UIStrings.receiveBadges),
233
- jslogContext: 'receive-badges',
234
- onClick: () => {
235
- this.detach();
236
- revealBadgeSettings();
237
- }
215
+ },
216
+ {
217
+ label: i18nString(UIStrings.receiveBadges),
218
+ jslogContext: 'receive-badges',
219
+ onClick: () => {
220
+ this.detach();
221
+ revealBadgeSettings();
238
222
  }
239
- ],
240
- imageUri: badge.imageUri,
241
- isStarterBadge: true,
242
- });
243
- return;
244
- }
223
+ }
224
+ ],
225
+ imageUri: badge.imageUri,
226
+ isStarterBadge: true,
227
+ });
228
+ }
245
229
 
246
- // The user does not have a GDP profile, starter badge acts as a nudge for creating a GDP profile.
230
+ #presentStarterBadgeProfileNudge(badge: Badges.Badge): void {
231
+ const googleDeveloperProgramLink = UI.XLink.XLink.create(
232
+ 'https://developers.google.com/program', lockedString('Google Developer Program'), 'badge-link', undefined,
233
+ 'program-link');
247
234
  this.#show({
248
235
  message: i18nFormatString(
249
236
  UIStrings.starterBadgeAwardMessageNoGdpProfile, {PH1: badge.title, PH2: googleDeveloperProgramLink}),
250
237
  jslogContext: badge.jslogContext,
251
238
  actions: [
252
239
  {
253
- label: i18nString(UIStrings.remindMeLater),
254
- jslogContext: 'remind-me-later',
240
+ label: i18nString(UIStrings.noThanks),
241
+ jslogContext: 'no-thanks',
255
242
  onClick: () => {
256
- this.detach();
257
- Badges.UserBadges.instance().snoozeStarterBadge();
243
+ this.#onDismissClick();
258
244
  },
259
245
  },
260
246
  {