chrome-devtools-frontend 1.0.1521880 → 1.0.1522145
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/front_end/core/host/GdpClient.ts +116 -66
- package/front_end/core/root/Runtime.ts +1 -0
- package/front_end/entrypoints/inspector_main/InspectorMain.ts +82 -32
- package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +1 -1
- package/front_end/entrypoints/main/MainImpl.ts +7 -1
- package/front_end/models/ai_assistance/agents/NetworkAgent.ts +10 -6
- package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +42 -4
- package/front_end/models/badges/UserBadges.ts +14 -16
- package/front_end/panels/ai_assistance/components/UserActionRow.ts +1 -2
- package/front_end/panels/application/IndexedDBViews.ts +1 -0
- package/front_end/panels/application/ReportingApiTreeElement.ts +1 -2
- package/front_end/panels/application/ReportingApiView.ts +18 -20
- package/front_end/panels/application/ServiceWorkerCacheViews.ts +3 -0
- package/front_end/panels/application/components/EndpointsGrid.ts +51 -59
- package/front_end/panels/application/components/ReportsGrid.ts +86 -107
- package/front_end/panels/application/components/StorageMetadataView.ts +30 -4
- package/front_end/panels/application/components/endpointsGrid.css +30 -0
- package/front_end/panels/application/components/reportsGrid.css +34 -0
- package/front_end/panels/application/components/storageMetadataView.css +9 -0
- package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +19 -27
- package/front_end/panels/common/BadgeNotification.ts +10 -3
- package/front_end/panels/network/NetworkPanel.ts +1 -1
- package/front_end/panels/search/SearchResultsPane.ts +14 -13
- package/front_end/panels/search/SearchView.ts +3 -20
- package/front_end/panels/settings/components/SyncSection.ts +8 -6
- package/front_end/panels/sources/SearchSourcesView.ts +1 -1
- package/front_end/panels/whats_new/ReleaseNoteText.ts +15 -11
- package/front_end/panels/whats_new/resources/WNDT.md +9 -6
- package/front_end/third_party/diff/README.chromium +0 -1
- package/front_end/ui/legacy/Treeoutline.ts +6 -9
- package/front_end/ui/legacy/UIUtils.ts +4 -17
- package/front_end/ui/legacy/Widget.ts +0 -5
- package/front_end/ui/legacy/XElement.ts +0 -33
- package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +3 -3
- package/front_end/ui/legacy/components/perf_ui/FilmStripView.ts +38 -21
- package/front_end/ui/legacy/components/perf_ui/filmStripView.css +29 -0
- package/front_end/ui/legacy/components/source_frame/XMLView.ts +3 -2
- package/front_end/ui/legacy/legacy.ts +0 -2
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- package/package.json +1 -1
- package/front_end/panels/application/components/reportingApiGrid.css +0 -31
- package/front_end/ui/legacy/XWidget.ts +0 -133
@@ -0,0 +1,34 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2025 The Chromium Authors
|
3
|
+
* Use of this source code is governed by a BSD-style license that can be
|
4
|
+
* found in the LICENSE file.
|
5
|
+
*/
|
6
|
+
|
7
|
+
@scope to (devtools-widget > *) {
|
8
|
+
:scope {
|
9
|
+
overflow: auto;
|
10
|
+
height: 100%;
|
11
|
+
}
|
12
|
+
|
13
|
+
.reporting-container {
|
14
|
+
height: 100%;
|
15
|
+
display: flex;
|
16
|
+
flex-direction: column;
|
17
|
+
width: 100%;
|
18
|
+
}
|
19
|
+
|
20
|
+
.reporting-header {
|
21
|
+
font-size: 15px;
|
22
|
+
background-color: var(--sys-color-surface2);
|
23
|
+
padding: 1px 4px;
|
24
|
+
flex-shrink: 0;
|
25
|
+
}
|
26
|
+
|
27
|
+
devtools-data-grid {
|
28
|
+
flex: auto;
|
29
|
+
}
|
30
|
+
|
31
|
+
.inline-icon {
|
32
|
+
vertical-align: text-bottom;
|
33
|
+
}
|
34
|
+
}
|
@@ -183,29 +183,23 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
183
183
|
'source-code': true,
|
184
184
|
'breakpoint-hit': input.highlightedItem === breakpoint,
|
185
185
|
});
|
186
|
-
const
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
if (expanded) {
|
204
|
-
output.userExpandedCategories.add(category);
|
205
|
-
} else {
|
206
|
-
output.userExpandedCategories.delete(category);
|
207
|
-
}
|
208
|
-
};
|
186
|
+
const onExpand =
|
187
|
+
(category: SDK.CategorizedBreakpoint.Category, {detail: {expanded}}: UI.TreeOutline.TreeViewElement.ExpandEvent):
|
188
|
+
void => {
|
189
|
+
const breakpoints = category && input.categories.get(category);
|
190
|
+
if (!breakpoints) {
|
191
|
+
return;
|
192
|
+
}
|
193
|
+
if (shouldExpandCategory(breakpoints)) {
|
194
|
+
// Basically ignore expand/collapse when the category is expanded by default.
|
195
|
+
return;
|
196
|
+
}
|
197
|
+
if (expanded) {
|
198
|
+
output.userExpandedCategories.add(category);
|
199
|
+
} else {
|
200
|
+
output.userExpandedCategories.delete(category);
|
201
|
+
}
|
202
|
+
};
|
209
203
|
|
210
204
|
render(
|
211
205
|
// clang-format off
|
@@ -219,17 +213,15 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
|
219
213
|
</devtools-toolbar>
|
220
214
|
<devtools-tree
|
221
215
|
${ref(e => { output.defaultFocus = e; })}
|
222
|
-
@expand=${onExpand}
|
223
216
|
.template=${html`
|
224
217
|
<ul role="tree">
|
225
218
|
${filteredCategories.map(([category, breakpoints]) => html`
|
226
|
-
<li
|
219
|
+
<li @expand=${(e: UI.TreeOutline.TreeViewElement.ExpandEvent) => onExpand(category, e)}
|
227
220
|
role="treeitem"
|
228
221
|
jslog-context=${category}
|
229
222
|
aria-checked=${breakpoints.some(breakpoint => breakpoint.enabled())
|
230
223
|
? breakpoints.some(breakpoint => !breakpoint.enabled()) ? 'mixed' : true
|
231
|
-
: false}
|
232
|
-
${trackCategoryConfigElement(category)}>
|
224
|
+
: false}>
|
233
225
|
<style>${categorizedBreakpointsSidebarPaneStyles}</style>
|
234
226
|
<devtools-checkbox
|
235
227
|
class="small"
|
@@ -192,7 +192,14 @@ export class BadgeNotification extends UI.Widget.Widget {
|
|
192
192
|
}
|
193
193
|
|
194
194
|
async #presentStarterBadge(badge: Badges.Badge): Promise<void> {
|
195
|
-
const
|
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);
|
196
203
|
const receiveBadgesSettingEnabled = Badges.UserBadges.instance().isReceiveBadgesSettingEnabled();
|
197
204
|
const googleDeveloperProgramLink = UI.XLink.XLink.create(
|
198
205
|
'https://developers.google.com/program', lockedString('Google Developer Program'), 'badge-link', undefined,
|
@@ -200,14 +207,14 @@ export class BadgeNotification extends UI.Widget.Widget {
|
|
200
207
|
|
201
208
|
// If the user already has a GDP profile and the receive badges setting enabled,
|
202
209
|
// starter badge behaves as if it's an activity based badge.
|
203
|
-
if (
|
210
|
+
if (hasGdpProfile && receiveBadgesSettingEnabled) {
|
204
211
|
this.#presentActivityBasedBadge(badge);
|
205
212
|
return;
|
206
213
|
}
|
207
214
|
|
208
215
|
// If the user already has a GDP profile and the receive badges setting disabled,
|
209
216
|
// starter badge behaves as a nudge for opting into receiving badges.
|
210
|
-
if (
|
217
|
+
if (hasGdpProfile && !receiveBadgesSettingEnabled) {
|
211
218
|
this.#show({
|
212
219
|
message: i18nFormatString(
|
213
220
|
UIStrings.starterBadgeAwardMessageSettingDisabled, {PH1: badge.title, PH2: googleDeveloperProgramLink}),
|
@@ -1050,7 +1050,7 @@ let searchNetworkViewInstance: SearchNetworkView;
|
|
1050
1050
|
|
1051
1051
|
export class SearchNetworkView extends Search.SearchView.SearchView {
|
1052
1052
|
private constructor() {
|
1053
|
-
super('network'
|
1053
|
+
super('network');
|
1054
1054
|
}
|
1055
1055
|
|
1056
1056
|
static instance(opts: {
|
@@ -52,23 +52,24 @@ export type View = (input: ViewInput, output: unknown, target: HTMLElement) => v
|
|
52
52
|
export const DEFAULT_VIEW: View = (input, _output, target) => {
|
53
53
|
const {results, matches, expandedResults, onSelectMatch, onExpandSearchResult, onShowMoreMatches} = input;
|
54
54
|
|
55
|
-
const onExpand =
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
};
|
55
|
+
const onExpand =
|
56
|
+
(searchResult: SearchResult, {detail: {expanded}}: UI.TreeOutline.TreeViewElement.ExpandEvent): void => {
|
57
|
+
if (expanded) {
|
58
|
+
expandedResults.add(searchResult);
|
59
|
+
onExpandSearchResult(searchResult);
|
60
|
+
} else {
|
61
|
+
expandedResults.delete(searchResult);
|
62
|
+
}
|
63
|
+
};
|
65
64
|
|
66
65
|
// clang-format off
|
67
66
|
render(html`
|
68
|
-
<devtools-tree hide-overflow
|
67
|
+
<devtools-tree hide-overflow .template=${html`
|
69
68
|
<ul role="tree">
|
70
|
-
${results.map(
|
71
|
-
<li
|
69
|
+
${results.map(searchResult => html`
|
70
|
+
<li @expand=${(e: UI.TreeOutline.TreeViewElement.ExpandEvent) => onExpand(searchResult, e)}
|
71
|
+
role="treeitem"
|
72
|
+
class="search-result">
|
72
73
|
<style>${searchResultsPaneStyles}</style>
|
73
74
|
${renderSearchResult(searchResult)}
|
74
75
|
<ul role="group" ?hidden=${!expandedResults.has(searchResult)}>
|
@@ -293,12 +293,9 @@ export class SearchView extends UI.Widget.VBox {
|
|
293
293
|
}>;
|
294
294
|
#searchScope: SearchScope|null;
|
295
295
|
|
296
|
-
// We throttle adding search results, otherwise we trigger DOM layout for each
|
297
|
-
// result added.
|
298
|
-
#throttler: Common.Throttler.Throttler;
|
299
296
|
#searchResults: SearchResult[] = [];
|
300
297
|
|
301
|
-
constructor(settingKey: string,
|
298
|
+
constructor(settingKey: string, view = DEFAULT_VIEW) {
|
302
299
|
super({
|
303
300
|
jslog: `${VisualLogging.panel('search').track({resize: true})}`,
|
304
301
|
useShadowDom: true,
|
@@ -316,7 +313,6 @@ export class SearchView extends UI.Widget.VBox {
|
|
316
313
|
this.#searchConfig = null;
|
317
314
|
this.#pendingSearchConfig = null;
|
318
315
|
this.#progress = null;
|
319
|
-
this.#throttler = throttler;
|
320
316
|
|
321
317
|
this.#advancedSearchConfig = Common.Settings.Settings.instance().createLocalSetting(
|
322
318
|
settingKey + '-search-config', new Workspace.SearchConfig.SearchConfig('', true, false).toPlainObject());
|
@@ -451,17 +447,8 @@ export class SearchView extends UI.Widget.VBox {
|
|
451
447
|
return;
|
452
448
|
}
|
453
449
|
this.#searchResults.push(searchResult);
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
#setSearchResults(): void {
|
458
|
-
this.#searchMatchesCount = 0;
|
459
|
-
this.#searchResultsCount = 0;
|
460
|
-
this.#nonEmptySearchResultsCount = 0;
|
461
|
-
for (const searchResult of this.#searchResults) {
|
462
|
-
this.#addSearchResult(searchResult);
|
463
|
-
}
|
464
|
-
this.performUpdate();
|
450
|
+
this.#addSearchResult(searchResult);
|
451
|
+
this.requestUpdate();
|
465
452
|
}
|
466
453
|
|
467
454
|
#onSearchFinished(searchId: number, finished: boolean): void {
|
@@ -640,8 +627,4 @@ export class SearchView extends UI.Widget.VBox {
|
|
640
627
|
this.#resetSearch();
|
641
628
|
this.#onClearSearchInput();
|
642
629
|
}
|
643
|
-
|
644
|
-
get throttlerForTest(): Common.Throttler.Throttler {
|
645
|
-
return this.#throttler;
|
646
|
-
}
|
647
630
|
}
|
@@ -11,7 +11,6 @@ import type * as Common from '../../../core/common/common.js';
|
|
11
11
|
import * as Host from '../../../core/host/host.js';
|
12
12
|
import * as i18n from '../../../core/i18n/i18n.js';
|
13
13
|
import type * as Platform from '../../../core/platform/platform.js';
|
14
|
-
import * as Root from '../../../core/root/root.js';
|
15
14
|
import * as SDK from '../../../core/sdk/sdk.js';
|
16
15
|
import * as Badges from '../../../models/badges/badges.js';
|
17
16
|
import * as Buttons from '../../../ui/components/buttons/buttons.js';
|
@@ -206,8 +205,13 @@ export class SyncSection extends HTMLElement {
|
|
206
205
|
return;
|
207
206
|
}
|
208
207
|
|
209
|
-
|
210
|
-
|
208
|
+
const getProfileResponse = await Host.GdpClient.GdpClient.instance().getProfile();
|
209
|
+
if (!getProfileResponse) {
|
210
|
+
return;
|
211
|
+
}
|
212
|
+
|
213
|
+
this.#gdpProfile = getProfileResponse.profile ?? undefined;
|
214
|
+
this.#isEligibleToCreateGdpProfile = getProfileResponse.isEligible;
|
211
215
|
void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#render);
|
212
216
|
}
|
213
217
|
}
|
@@ -310,9 +314,7 @@ function renderGdpSectionIfNeeded({
|
|
310
314
|
if (!Host.GdpClient.isGdpProfilesAvailable() || (!gdpProfile && !isEligibleToCreateProfile)) {
|
311
315
|
return Lit.nothing;
|
312
316
|
}
|
313
|
-
const hasReceiveBadgesCheckbox =
|
314
|
-
Host.GdpClient.getGdpProfilesEnterprisePolicy() === Root.Runtime.GdpProfilesEnterprisePolicyValue.ENABLED;
|
315
|
-
|
317
|
+
const hasReceiveBadgesCheckbox = Host.GdpClient.isBadgesEnabled() && receiveBadgesSetting;
|
316
318
|
function renderBrand(): Lit.LitTemplate {
|
317
319
|
// clang-format off
|
318
320
|
return html`
|
@@ -17,7 +17,7 @@ export class SearchSources {
|
|
17
17
|
|
18
18
|
export class SearchSourcesView extends Search.SearchView.SearchView {
|
19
19
|
constructor() {
|
20
|
-
super('sources'
|
20
|
+
super('sources');
|
21
21
|
}
|
22
22
|
|
23
23
|
override createScope(): Search.SearchScope.SearchScope {
|
@@ -40,28 +40,32 @@ export function getReleaseNote(): ReleaseNote {
|
|
40
40
|
}
|
41
41
|
|
42
42
|
let releaseNote: ReleaseNote = {
|
43
|
-
version:
|
44
|
-
header: 'What\'s new in DevTools
|
43
|
+
version: 83,
|
44
|
+
header: 'What\'s new in DevTools 142',
|
45
45
|
markdownLinks: [
|
46
46
|
{
|
47
|
-
key: 'ai-
|
48
|
-
link: 'https://developer.chrome.com/blog/new-in-devtools-
|
47
|
+
key: 'perf-ai-agent',
|
48
|
+
link: 'https://developer.chrome.com/blog/new-in-devtools-142/#perf-ai-agent',
|
49
49
|
},
|
50
50
|
{
|
51
|
-
key: 'ai-
|
52
|
-
link: 'https://developer.chrome.com/blog/new-in-devtools-
|
51
|
+
key: 'ai-code-completion',
|
52
|
+
link: 'https://developer.chrome.com/blog/new-in-devtools-142/#ai-code-completion',
|
53
53
|
},
|
54
54
|
{
|
55
|
-
key: '
|
56
|
-
link: 'https://developer.chrome.com/blog/new-in-devtools-
|
55
|
+
key: 'gdp',
|
56
|
+
link: 'https://developer.chrome.com/blog/new-in-devtools-142/#gdp',
|
57
|
+
},
|
58
|
+
{
|
59
|
+
key: 'ai-main-button',
|
60
|
+
link: 'https://developer.chrome.com/blog/new-in-devtools-142/#ai-main-button',
|
57
61
|
},
|
58
62
|
],
|
59
63
|
videoLinks: [
|
60
64
|
{
|
61
|
-
description: 'See past highlights from Chrome
|
62
|
-
link: 'https://developer.chrome.com/blog/new-in-devtools-
|
65
|
+
description: 'See past highlights from Chrome 141',
|
66
|
+
link: 'https://developer.chrome.com/blog/new-in-devtools-141' as Platform.DevToolsPath.UrlString,
|
63
67
|
type: VideoType.WHATS_NEW,
|
64
68
|
},
|
65
69
|
],
|
66
|
-
link: 'https://developer.chrome.com/blog/new-in-devtools-
|
70
|
+
link: 'https://developer.chrome.com/blog/new-in-devtools-142/',
|
67
71
|
};
|
@@ -1,8 +1,11 @@
|
|
1
|
-
### [
|
2
|
-
|
1
|
+
### [Full stack trace AI agent in Performance panel](perf-ai-agent)
|
2
|
+
The Performance panel now integrates a more capable AI agent that has full access to the stack trace.
|
3
3
|
|
4
|
-
### [
|
5
|
-
|
4
|
+
### [AI code completion in Sources and Console](ai-code-completion)
|
5
|
+
Code completion powered by AI is now available in the Sources panel and the Console.
|
6
6
|
|
7
|
-
### [
|
8
|
-
|
7
|
+
### [Google Developer Program support](gdp)
|
8
|
+
The Google Developer Program, a ready-made subscription and community platform, is now in DevTools, offering a more personalized experience, a badge system, and easier discovery of new features.
|
9
|
+
|
10
|
+
### [One main 'Debug with AI' button](ai-main-button)
|
11
|
+
The primary action bar at the top of DevTools now features the primary "Debug with AI" button which opens the 'AI assistance' panel in a right-hand side bar.
|
@@ -3,7 +3,6 @@ Short Name: diff-match-patch
|
|
3
3
|
URL: https://github.com/google/diff-match-patch/tree/master/javascript
|
4
4
|
Version: 5.60.0
|
5
5
|
Revision: 0ae308daa77aeddb089cd6b7b0a443fca026266e
|
6
|
-
Update Mechanism: Manual
|
7
6
|
License: Apache-2.0
|
8
7
|
License File: LICENSE
|
9
8
|
Update Mechanism: Static.HardFork (https://crbug.com/422918273)
|
@@ -1637,7 +1637,7 @@ function getTreeNodes(nodeList: NodeList|Node[]): HTMLLIElement[] {
|
|
1637
1637
|
* <devtools-tree
|
1638
1638
|
* .template=${html`
|
1639
1639
|
* <ul role="tree">
|
1640
|
-
* <li role="treeitem">
|
1640
|
+
* <li role="treeitem" @expand=${onExpand}>
|
1641
1641
|
* Tree Node Text
|
1642
1642
|
* <ul role="group">
|
1643
1643
|
* Node with subtree
|
@@ -1659,7 +1659,7 @@ function getTreeNodes(nodeList: NodeList|Node[]): HTMLLIElement[] {
|
|
1659
1659
|
* tree node). If a tree node contains a <ul role="group">, that defines a subtree under that tree node. The `hidden`
|
1660
1660
|
* attribute on the <ul> defines whether that subtree should render as collapsed. Note that node expanding/collapsing do
|
1661
1661
|
* not reflect this state back to the attribute on the config element, those state changes are rather sent out as
|
1662
|
-
* `expand` events.
|
1662
|
+
* `expand` events on the config element.
|
1663
1663
|
*
|
1664
1664
|
* Under the hood this uses TreeOutline.
|
1665
1665
|
*
|
@@ -1687,7 +1687,6 @@ function getTreeNodes(nodeList: NodeList|Node[]): HTMLLIElement[] {
|
|
1687
1687
|
*
|
1688
1688
|
* @property template Define the tree contents
|
1689
1689
|
* @event selected A node was selected
|
1690
|
-
* @event expand A subtree was expanded or collapsed
|
1691
1690
|
* @attribute navigation-variant Turn this tree into the navigation variant
|
1692
1691
|
* @attribute hide-overflow
|
1693
1692
|
*/
|
@@ -1704,14 +1703,12 @@ export class TreeViewElement extends HTMLElementWithLightDOMTemplate {
|
|
1704
1703
|
});
|
1705
1704
|
this.#treeOutline.addEventListener(Events.ElementExpanded, event => {
|
1706
1705
|
if (event.data instanceof TreeViewTreeElement) {
|
1707
|
-
|
1708
|
-
{expanded: true, target: (event.data as TreeViewTreeElement).configElement}));
|
1706
|
+
event.data.listItemElement.dispatchEvent(new TreeViewElement.ExpandEvent({expanded: true}));
|
1709
1707
|
}
|
1710
1708
|
});
|
1711
1709
|
this.#treeOutline.addEventListener(Events.ElementCollapsed, event => {
|
1712
1710
|
if (event.data instanceof TreeViewTreeElement) {
|
1713
|
-
|
1714
|
-
{expanded: false, target: (event.data as TreeViewTreeElement).configElement}));
|
1711
|
+
event.data.listItemElement.dispatchEvent(new TreeViewElement.ExpandEvent({expanded: false}));
|
1715
1712
|
}
|
1716
1713
|
});
|
1717
1714
|
this.addNodes(getTreeNodes([this]));
|
@@ -1832,8 +1829,8 @@ export namespace TreeViewElement {
|
|
1832
1829
|
}
|
1833
1830
|
}
|
1834
1831
|
|
1835
|
-
export class ExpandEvent extends CustomEvent<{expanded: boolean
|
1836
|
-
constructor(detail: {expanded: boolean
|
1832
|
+
export class ExpandEvent extends CustomEvent<{expanded: boolean}> {
|
1833
|
+
constructor(detail: {expanded: boolean}) {
|
1837
1834
|
super('expand', {detail});
|
1838
1835
|
}
|
1839
1836
|
}
|
@@ -62,7 +62,6 @@ import smallBubbleStyles from './smallBubble.css.js';
|
|
62
62
|
import type {ToolbarButton} from './Toolbar.js';
|
63
63
|
import {Tooltip} from './Tooltip.js';
|
64
64
|
import {Widget} from './Widget.js';
|
65
|
-
import type {XWidget} from './XWidget.js';
|
66
65
|
|
67
66
|
declare global {
|
68
67
|
interface HTMLElementTagNameMap {
|
@@ -1935,27 +1934,11 @@ function updateWidgetfocusWidgetForNode(node: Node|null): void {
|
|
1935
1934
|
}
|
1936
1935
|
}
|
1937
1936
|
|
1938
|
-
function updateXWidgetfocusWidgetForNode(node: Node|null): void {
|
1939
|
-
node = node?.parentNodeOrShadowHost() ?? null;
|
1940
|
-
const XWidgetConstructor = customElements.get('x-widget') as Platform.Constructor.Constructor<XWidget>| undefined;
|
1941
|
-
let widget = null;
|
1942
|
-
while (node) {
|
1943
|
-
if (XWidgetConstructor && node instanceof XWidgetConstructor) {
|
1944
|
-
if (widget) {
|
1945
|
-
node.defaultFocusedElement = widget;
|
1946
|
-
}
|
1947
|
-
widget = node;
|
1948
|
-
}
|
1949
|
-
node = node.parentNodeOrShadowHost();
|
1950
|
-
}
|
1951
|
-
}
|
1952
|
-
|
1953
1937
|
function focusChanged(event: Event): void {
|
1954
1938
|
const target = event.target as HTMLElement;
|
1955
1939
|
const document = target ? target.ownerDocument : null;
|
1956
1940
|
const element = document ? Platform.DOMUtilities.deepActiveElement(document) : null;
|
1957
1941
|
updateWidgetfocusWidgetForNode(element);
|
1958
|
-
updateXWidgetfocusWidgetForNode(element);
|
1959
1942
|
}
|
1960
1943
|
|
1961
1944
|
/**
|
@@ -2282,6 +2265,10 @@ export class HTMLElementWithLightDOMTemplate extends HTMLElement {
|
|
2282
2265
|
}
|
2283
2266
|
}
|
2284
2267
|
|
2268
|
+
get templateRoot(): DocumentFragment|HTMLElement {
|
2269
|
+
return this.#contentTemplate?.content ?? this;
|
2270
|
+
}
|
2271
|
+
|
2285
2272
|
set template(template: Lit.LitTemplate) {
|
2286
2273
|
if (!this.#contentTemplate) {
|
2287
2274
|
this.removeChildren();
|
@@ -36,7 +36,6 @@ import * as Geometry from '../../models/geometry/geometry.js';
|
|
36
36
|
import * as Lit from '../../ui/lit/lit.js';
|
37
37
|
|
38
38
|
import {createShadowRootWithCoreStyles} from './UIUtils.js';
|
39
|
-
import {XWidget} from './XWidget.js';
|
40
39
|
|
41
40
|
// Remember the original DOM mutation methods here, since we
|
42
41
|
// will override them below to sanity check the Widget system.
|
@@ -757,10 +756,6 @@ export class Widget {
|
|
757
756
|
}
|
758
757
|
let child = this.contentElement.traverseNextNode(this.contentElement);
|
759
758
|
while (child) {
|
760
|
-
if (child instanceof XWidget) {
|
761
|
-
child.focus();
|
762
|
-
return;
|
763
|
-
}
|
764
759
|
child = child.traverseNextNode(this.contentElement);
|
765
760
|
}
|
766
761
|
}
|
@@ -39,36 +39,3 @@ export class XElement extends HTMLElement {
|
|
39
39
|
}
|
40
40
|
}
|
41
41
|
}
|
42
|
-
|
43
|
-
class XBox extends XElement {
|
44
|
-
constructor(direction: string) {
|
45
|
-
super();
|
46
|
-
this.style.setProperty('display', 'flex');
|
47
|
-
this.style.setProperty('flex-direction', direction);
|
48
|
-
this.style.setProperty('justify-content', 'flex-start');
|
49
|
-
}
|
50
|
-
|
51
|
-
static override get observedAttributes(): string[] {
|
52
|
-
return super.observedAttributes.concat(['x-start', 'x-center', 'x-stretch', 'x-baseline', 'justify-content']);
|
53
|
-
}
|
54
|
-
|
55
|
-
override attributeChangedCallback(attr: string, oldValue: string|null, newValue: string|null): void {
|
56
|
-
if (attr === 'x-start' || attr === 'x-center' || attr === 'x-stretch' || attr === 'x-baseline') {
|
57
|
-
if (newValue === null) {
|
58
|
-
this.style.removeProperty('align-items');
|
59
|
-
} else {
|
60
|
-
this.style.setProperty('align-items', attr === 'x-start' ? 'flex-start' : attr.substr(2));
|
61
|
-
}
|
62
|
-
return;
|
63
|
-
}
|
64
|
-
super.attributeChangedCallback(attr, oldValue, newValue);
|
65
|
-
}
|
66
|
-
}
|
67
|
-
|
68
|
-
class XHBox extends XBox {
|
69
|
-
constructor() {
|
70
|
-
super('row');
|
71
|
-
}
|
72
|
-
}
|
73
|
-
|
74
|
-
customElements.define('x-hbox', XHBox);
|
@@ -95,7 +95,7 @@ class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate {
|
|
95
95
|
|
96
96
|
this.#resizeObserver.observe(this);
|
97
97
|
this.#updateColumns();
|
98
|
-
this.addNodes(this.querySelectorAll('tr'));
|
98
|
+
this.addNodes(this.templateRoot.querySelectorAll('tr'));
|
99
99
|
}
|
100
100
|
|
101
101
|
attributeChangedCallback(name: string, oldValue: string|null, newValue: string|null): void {
|
@@ -155,7 +155,7 @@ class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate {
|
|
155
155
|
this.#hideableColumns.clear();
|
156
156
|
this.#columns = [];
|
157
157
|
let hasEditableColumn = false;
|
158
|
-
for (const column of this.querySelectorAll('th[id]') || []) {
|
158
|
+
for (const column of this.templateRoot.querySelectorAll('th[id]') || []) {
|
159
159
|
const id = column.id as Lowercase<string>;
|
160
160
|
let title = column.textContent?.trim() || '';
|
161
161
|
const titleDOMFragment = column.firstElementChild ? document.createDocumentFragment() : undefined;
|
@@ -308,7 +308,7 @@ class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate {
|
|
308
308
|
this.#usedCreationNode = null;
|
309
309
|
this.#dataGrid.creationNode = undefined;
|
310
310
|
}
|
311
|
-
const placeholder = this.querySelector('tr[placeholder]');
|
311
|
+
const placeholder = this.templateRoot.querySelector('tr[placeholder]');
|
312
312
|
if (!placeholder) {
|
313
313
|
this.#dataGrid.creationNode?.remove();
|
314
314
|
this.#dataGrid.creationNode = undefined;
|
@@ -149,8 +149,7 @@ interface DialogParsedTrace {
|
|
149
149
|
}
|
150
150
|
|
151
151
|
export class Dialog {
|
152
|
-
private
|
153
|
-
private readonly widget: UI.XWidget.XWidget;
|
152
|
+
private readonly widget: UI.Widget.Widget;
|
154
153
|
private index: number;
|
155
154
|
private dialog: UI.Dialog.Dialog|null = null;
|
156
155
|
|
@@ -173,21 +172,32 @@ export class Dialog {
|
|
173
172
|
UI.Tooltip.Tooltip.install(prevButton, i18nString(UIStrings.previousFrame));
|
174
173
|
const nextButton = UI.UIUtils.createTextButton('\u25B6', this.onNextFrame.bind(this));
|
175
174
|
UI.Tooltip.Tooltip.install(nextButton, i18nString(UIStrings.nextFrame));
|
176
|
-
this.
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
175
|
+
this.widget = new UI.Widget.Widget({classes: ['film-strip-image-dialog']});
|
176
|
+
this.widget.registerRequiredCSS(filmStripViewStyles);
|
177
|
+
|
178
|
+
const imageBox = document.createElement('div');
|
179
|
+
imageBox.classList.add('image-box');
|
180
|
+
|
181
|
+
const image = document.createElement('img');
|
182
|
+
image.setAttribute('data-film-strip-dialog-img', '');
|
183
|
+
imageBox.append(image);
|
184
|
+
|
185
|
+
const buttonBox = document.createElement('div');
|
186
|
+
buttonBox.classList.add('button-box');
|
187
|
+
|
188
|
+
const timeBox = document.createElement('div');
|
189
|
+
timeBox.classList.add('time-box');
|
190
|
+
|
191
|
+
buttonBox.append(prevButton);
|
192
|
+
buttonBox.append(timeBox);
|
193
|
+
buttonBox.append(nextButton);
|
194
|
+
|
195
|
+
this.widget.contentElement.append(imageBox);
|
196
|
+
this.widget.contentElement.append(buttonBox);
|
197
|
+
|
198
|
+
this.widget.element.tabIndex = 0;
|
199
|
+
this.widget.contentElement.append();
|
200
|
+
this.widget.contentElement.addEventListener('keydown', this.keyDown.bind(this), false);
|
191
201
|
this.dialog = null;
|
192
202
|
|
193
203
|
void this.render();
|
@@ -210,8 +220,8 @@ export class Dialog {
|
|
210
220
|
private resize(): void {
|
211
221
|
if (!this.dialog) {
|
212
222
|
this.dialog = new UI.Dialog.Dialog();
|
213
|
-
this.
|
214
|
-
this.dialog.setDefaultFocusedElement(this.widget);
|
223
|
+
this.widget.show(this.dialog.contentElement);
|
224
|
+
this.dialog.setDefaultFocusedElement(this.widget.element);
|
215
225
|
this.dialog.show();
|
216
226
|
}
|
217
227
|
this.dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.MEASURE_CONTENT);
|
@@ -273,8 +283,15 @@ export class Dialog {
|
|
273
283
|
private render(): void {
|
274
284
|
const frame = this.#data.frames[this.index];
|
275
285
|
const timestamp = Trace.Helpers.Timing.microToMilli(frame.screenshotEvent.ts);
|
276
|
-
|
277
|
-
|
286
|
+
const timeBox = this.widget.contentElement.querySelector('.time-box');
|
287
|
+
if (timeBox) {
|
288
|
+
timeBox.textContent = i18n.TimeUtilities.millisToString(timestamp - this.#zeroTime());
|
289
|
+
}
|
290
|
+
|
291
|
+
const image = this.widget.contentElement.querySelector('img');
|
292
|
+
if (!image) {
|
293
|
+
return;
|
294
|
+
}
|
278
295
|
image.setAttribute('data-frame-index', this.index.toString());
|
279
296
|
const imgData = Trace.Handlers.ModelHandlers.Screenshots.screenshotImageDataUri(frame.screenshotEvent);
|
280
297
|
FilmStripView.setImageData(image, imgData);
|