chrome-devtools-frontend
Version:
Chrome DevTools UI
100 lines (79 loc) • 3.36 kB
text/typescript
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import * as i18n from '../../../../core/i18n/i18n.js';
import type {LCPDiscoveryInsightModel} from '../../../../models/trace/insights/LCPDiscovery.js';
import * as Trace from '../../../../models/trace/trace.js';
import * as uiI18n from '../../../../ui/i18n/i18n.js';
import * as UI from '../../../../ui/legacy/legacy.js';
import * as Lit from '../../../../ui/lit/lit.js';
import {BaseInsightComponent} from './BaseInsightComponent.js';
import {Checklist} from './Checklist.js';
import {imageRef} from './ImageRef.js';
const {widget} = UI.Widget;
const {UIStrings, i18nString, getImageData} = Trace.Insights.Models.LCPDiscovery;
const {html} = Lit;
// eslint-disable-next-line @devtools/l10n-filename-matches
const str_ = i18n.i18n.registerUIStrings('models/trace/insights/LCPDiscovery.ts', UIStrings);
export class LCPDiscovery extends BaseInsightComponent<LCPDiscoveryInsightModel> {
override internalName = 'lcp-discovery';
protected override hasAskAiSupport(): boolean {
return true;
}
protected override createOverlays(): Trace.Types.Overlays.Overlay[] {
if (!this.model) {
return [];
}
const overlays = this.model.createOverlays?.();
if (!overlays) {
return [];
}
const imageResults = getImageData(this.model);
if (!imageResults?.discoveryDelay) {
return [];
}
const timespanOverlaySection = overlays.find(overlay => overlay.type === 'TIMESPAN_BREAKDOWN')?.sections[0];
if (timespanOverlaySection) {
timespanOverlaySection.label = this.#renderDiscoveryDelay(imageResults.discoveryDelay);
}
return overlays;
}
override getEstimatedSavingsTime(): Trace.Types.Timing.Milli|null {
if (!this.model) {
return null;
}
return getImageData(this.model)?.estimatedSavings ?? null;
}
#renderDiscoveryDelay(delay: Trace.Types.Timing.Micro): HTMLElement {
// Trace.Types.Overlays.TimespanBreakdownEntryBreakdown needs an HTMLElement, which we have to localize here.
/* eslint-disable @devtools/no-imperative-dom-api */
const timeWrapper = document.createElement('span');
timeWrapper.classList.add('discovery-time-ms');
timeWrapper.innerText = i18n.TimeUtilities.formatMicroSecondsAsMillisFixed(delay);
return uiI18n.getFormatLocalizedString(str_, UIStrings.lcpLoadDelay, {PH1: timeWrapper});
/* eslint-enable @devtools/no-imperative-dom-api */
}
override renderContent(): Lit.LitTemplate {
if (!this.model) {
return Lit.nothing;
}
const imageData = getImageData(this.model);
if (!imageData) {
if (!this.model.lcpEvent) {
return html`<div class="insight-section">${i18nString(UIStrings.noLcp)}</div>`;
}
return html`<div class="insight-section">${i18nString(UIStrings.noLcpResource)}</div>`;
}
let delayEl;
if (imageData.discoveryDelay) {
delayEl = html`<div>${this.#renderDiscoveryDelay(imageData.discoveryDelay)}</div>`;
}
// clang-format off
return html`
<div class="insight-section">
${widget(Checklist, {checklist: imageData.checklist})}
<div class="insight-section">${imageRef(imageData.request)}${delayEl}</div>
</div>`;
// clang-format on
}
}