chrome-devtools-frontend
Version:
Chrome DevTools UI
210 lines (172 loc) • 6.83 kB
text/typescript
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import * as CSSOverviewComponents from './components/components.js';
import cssOverviewStyles from './cssOverview.css.js';
import type * as Common from '../../core/common/common.js';
import * as Host from '../../core/host/host.js';
import * as SDK from '../../core/sdk/sdk.js';
import * as UI from '../../ui/legacy/legacy.js';
import type * as Protocol from '../../generated/protocol.js';
import {CSSOverviewCompletedView, type ContrastIssue} from './CSSOverviewCompletedView.js';
import {Events, type OverviewController} from './CSSOverviewController.js';
import {CSSOverviewModel, type GlobalStyleStats} from './CSSOverviewModel.js';
import {CSSOverviewProcessingView} from './CSSOverviewProcessingView.js';
import {type UnusedDeclaration} from './CSSOverviewUnusedDeclarations.js';
export class CSSOverviewPanel extends UI.Panel.Panel implements SDK.TargetManager.Observer {
readonly #controller: OverviewController;
readonly #startView: CSSOverviewComponents.CSSOverviewStartView.CSSOverviewStartView;
readonly #processingView: CSSOverviewProcessingView;
readonly #completedView: CSSOverviewCompletedView;
#model?: CSSOverviewModel;
#backgroundColors!: Map<string, Set<Protocol.DOM.BackendNodeId>>;
#textColors!: Map<string, Set<Protocol.DOM.BackendNodeId>>;
#fillColors!: Map<string, Set<Protocol.DOM.BackendNodeId>>;
#borderColors!: Map<string, Set<Protocol.DOM.BackendNodeId>>;
#fontInfo!: Map<string, Map<string, Map<string, Protocol.DOM.BackendNodeId[]>>>;
#mediaQueries!: Map<string, Protocol.CSS.CSSMedia[]>;
#unusedDeclarations!: Map<string, UnusedDeclaration[]>;
#elementCount!: number;
#globalStyleStats!: GlobalStyleStats;
#textColorContrastIssues!: Map<string, ContrastIssue[]>;
constructor(controller: OverviewController) {
super('css_overview');
this.element.classList.add('css-overview-panel');
this.#controller = controller;
this.#startView = new CSSOverviewComponents.CSSOverviewStartView.CSSOverviewStartView();
this.#startView.addEventListener(
'overviewstartrequested', () => this.#controller.dispatchEventToListeners(Events.RequestOverviewStart));
this.#processingView = new CSSOverviewProcessingView(this.#controller);
this.#completedView = new CSSOverviewCompletedView(this.#controller);
SDK.TargetManager.TargetManager.instance().observeTargets(this);
this.#controller.addEventListener(Events.RequestOverviewStart, _event => {
Host.userMetrics.actionTaken(Host.UserMetrics.Action.CaptureCssOverviewClicked);
void this.#startOverview();
}, this);
this.#controller.addEventListener(Events.OverviewCompleted, this.#overviewCompleted, this);
this.#controller.addEventListener(Events.Reset, this.#reset, this);
this.#controller.addEventListener(Events.RequestNodeHighlight, this.#requestNodeHighlight, this);
this.#reset();
}
targetAdded(target: SDK.Target.Target): void {
if (target !== SDK.TargetManager.TargetManager.instance().primaryPageTarget()) {
return;
}
this.#completedView.initializeModels(target);
const model = target.model(CSSOverviewModel);
this.#model = (model as CSSOverviewModel);
}
targetRemoved(): void {
}
#getModel(): CSSOverviewModel {
if (!this.#model) {
throw new Error('Did not retrieve model information yet.');
}
return this.#model;
}
#reset(): void {
this.#backgroundColors = new Map();
this.#textColors = new Map();
this.#fillColors = new Map();
this.#borderColors = new Map();
this.#fontInfo = new Map();
this.#mediaQueries = new Map();
this.#unusedDeclarations = new Map();
this.#elementCount = 0;
this.#globalStyleStats = {
styleRules: 0,
inlineStyles: 0,
externalSheets: 0,
stats: {
// Simple.
type: 0,
class: 0,
id: 0,
universal: 0,
attribute: 0,
// Non-simple.
nonSimple: 0,
},
};
this.#textColorContrastIssues = new Map();
this.#renderInitialView();
}
#requestNodeHighlight(evt: Common.EventTarget.EventTargetEvent<number>): void {
this.#getModel().highlightNode((evt.data as Protocol.DOM.BackendNodeId));
}
#renderInitialView(): void {
this.#processingView.hideWidget();
this.#completedView.hideWidget();
this.contentElement.append(this.#startView);
this.#startView.show();
}
#renderOverviewStartedView(): void {
this.#startView.hide();
this.#completedView.hideWidget();
this.#processingView.show(this.contentElement);
}
#renderOverviewCompletedView(): void {
this.#startView.hide();
this.#processingView.hideWidget();
this.#completedView.show(this.contentElement);
this.#completedView.setOverviewData({
backgroundColors: this.#backgroundColors,
textColors: this.#textColors,
textColorContrastIssues: this.#textColorContrastIssues,
fillColors: this.#fillColors,
borderColors: this.#borderColors,
globalStyleStats: this.#globalStyleStats,
fontInfo: this.#fontInfo,
elementCount: this.#elementCount,
mediaQueries: this.#mediaQueries,
unusedDeclarations: this.#unusedDeclarations,
});
}
async #startOverview(): Promise<void> {
this.#renderOverviewStartedView();
const model = this.#getModel();
const [globalStyleStats, { elementCount, backgroundColors, textColors, textColorContrastIssues, fillColors, borderColors, fontInfo, unusedDeclarations }, mediaQueries] = await Promise.all([
model.getGlobalStylesheetStats(),
model.getNodeStyleStats(),
model.getMediaQueries(),
]);
if (elementCount) {
this.#elementCount = elementCount;
}
if (globalStyleStats) {
this.#globalStyleStats = globalStyleStats;
}
if (mediaQueries) {
this.#mediaQueries = mediaQueries;
}
if (backgroundColors) {
this.#backgroundColors = backgroundColors;
}
if (textColors) {
this.#textColors = textColors;
}
if (textColorContrastIssues) {
this.#textColorContrastIssues = textColorContrastIssues;
}
if (fillColors) {
this.#fillColors = fillColors;
}
if (borderColors) {
this.#borderColors = borderColors;
}
if (fontInfo) {
this.#fontInfo = fontInfo;
}
if (unusedDeclarations) {
this.#unusedDeclarations = unusedDeclarations;
}
this.#controller.dispatchEventToListeners(Events.OverviewCompleted);
}
#overviewCompleted(): void {
this.#renderOverviewCompletedView();
}
override wasShown(): void {
super.wasShown();
this.registerCSSFiles([cssOverviewStyles]);
}
}