chrome-devtools-frontend
Version:
Chrome DevTools UI
183 lines (157 loc) • 6.85 kB
text/typescript
// Copyright 2023 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.
/* eslint-disable rulesdir/no-imperative-dom-api */
import type * as Common from '../../core/common/common.js';
import * as i18n from '../../core/i18n/i18n.js';
import * as Platform from '../../core/platform/platform.js';
import * as SDK from '../../core/sdk/sdk.js';
import type * as Protocol from '../../generated/protocol.js';
import * as Bindings from '../../models/bindings/bindings.js';
import * as UI from '../../ui/legacy/legacy.js';
import outermostTargetSelectorStyles from './outermostTargetSelector.css.js';
const UIStrings = {
/**
*@description Title of toolbar item in outermost target selector in the main toolbar
*/
targetNotSelected: 'Page: Not selected',
/**
*@description Title of toolbar item in outermost target selector in the main toolbar
*@example {top} PH1
*/
targetS: 'Page: {PH1}',
} as const;
const str_ = i18n.i18n.registerUIStrings('entrypoints/inspector_main/OutermostTargetSelector.ts', UIStrings);
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
let outermostTargetSelectorInstance: OutermostTargetSelector;
export class OutermostTargetSelector implements SDK.TargetManager.Observer, UI.SoftDropDown.Delegate<SDK.Target.Target>,
UI.Toolbar.Provider {
readonly listItems = new UI.ListModel.ListModel<SDK.Target.Target>();
readonly #dropDown: UI.SoftDropDown.SoftDropDown<SDK.Target.Target>;
readonly #toolbarItem: UI.Toolbar.ToolbarItem;
constructor() {
this.#dropDown = new UI.SoftDropDown.SoftDropDown(this.listItems, this);
this.#dropDown.setRowHeight(36);
this.#toolbarItem = new UI.Toolbar.ToolbarItem(this.#dropDown.element);
this.#toolbarItem.setTitle(i18nString(UIStrings.targetNotSelected));
this.listItems.addEventListener(
UI.ListModel.Events.ITEMS_REPLACED, () => this.#toolbarItem.setEnabled(Boolean(this.listItems.length)));
this.#toolbarItem.element.classList.add('toolbar-has-dropdown');
const targetManager = SDK.TargetManager.TargetManager.instance();
targetManager.addModelListener(
SDK.ChildTargetManager.ChildTargetManager, SDK.ChildTargetManager.Events.TARGET_INFO_CHANGED,
this.#onTargetInfoChanged, this);
targetManager.addEventListener(SDK.TargetManager.Events.NAME_CHANGED, this.#onInspectedURLChanged, this);
targetManager.observeTargets(this);
UI.Context.Context.instance().addFlavorChangeListener(SDK.Target.Target, this.#targetChanged, this);
}
static instance(opts: {
forceNew: boolean|null,
} = {forceNew: null}): OutermostTargetSelector {
const {forceNew} = opts;
if (!outermostTargetSelectorInstance || forceNew) {
outermostTargetSelectorInstance = new OutermostTargetSelector();
}
return outermostTargetSelectorInstance;
}
item(): UI.Toolbar.ToolbarItem {
return this.#toolbarItem;
}
highlightedItemChanged(
_from: SDK.Target.Target|null, _to: SDK.Target.Target|null, fromElement: Element|null,
toElement: Element|null): void {
if (fromElement) {
fromElement.classList.remove('highlighted');
}
if (toElement) {
toElement.classList.add('highlighted');
}
}
titleFor(target: SDK.Target.Target): string {
return target.name();
}
targetAdded(target: SDK.Target.Target): void {
if (target.outermostTarget() !== target) {
return;
}
this.listItems.insertWithComparator(target, this.#targetComparator());
this.#toolbarItem.setVisible(this.listItems.length > 1);
if (target === UI.Context.Context.instance().flavor(SDK.Target.Target)) {
this.#dropDown.selectItem(target);
}
}
targetRemoved(target: SDK.Target.Target): void {
const index = this.listItems.indexOf(target);
if (index === -1) {
return;
}
this.listItems.remove(index);
this.#toolbarItem.setVisible(this.listItems.length > 1);
}
#targetComparator() {
return (a: SDK.Target.Target, b: SDK.Target.Target) => {
const aTargetInfo = a.targetInfo();
const bTargetInfo = b.targetInfo();
if (!aTargetInfo || !bTargetInfo) {
return 0;
}
if (!aTargetInfo.subtype?.length && bTargetInfo.subtype?.length) {
return -1;
}
if (aTargetInfo.subtype?.length && !bTargetInfo.subtype?.length) {
return 1;
}
return aTargetInfo.url.localeCompare(bTargetInfo.url);
};
}
#onTargetInfoChanged(event: Common.EventTarget.EventTargetEvent<Protocol.Target.TargetInfo>): void {
const targetManager = SDK.TargetManager.TargetManager.instance();
const target = targetManager.targetById(event.data.targetId);
if (!target || target.outermostTarget() !== target) {
return;
}
this.targetRemoved(target);
this.targetAdded(target);
}
#onInspectedURLChanged(event: Common.EventTarget.EventTargetEvent<SDK.Target.Target>): void {
const target = event.data;
if (!target || target.outermostTarget() !== target) {
return;
}
this.targetRemoved(target);
this.targetAdded(target);
}
#targetChanged({
data: target,
}: Common.EventTarget.EventTargetEvent<SDK.Target.Target|null>): void {
this.#dropDown.selectItem(target?.outermostTarget() || null);
}
createElementForItem(item: SDK.Target.Target): Element {
const element = document.createElement('div');
element.classList.add('target');
const shadowRoot = UI.UIUtils.createShadowRootWithCoreStyles(element, {cssFile: outermostTargetSelectorStyles});
const title = shadowRoot.createChild('div', 'title');
UI.UIUtils.createTextChild(title, Platform.StringUtilities.trimEndWithMaxLength(this.titleFor(item), 100));
const subTitle = shadowRoot.createChild('div', 'subtitle');
UI.UIUtils.createTextChild(subTitle, this.#subtitleFor(item));
return element;
}
#subtitleFor(target: SDK.Target.Target): string {
const targetInfo = target.targetInfo();
if (target === SDK.TargetManager.TargetManager.instance().primaryPageTarget() && targetInfo) {
return Bindings.ResourceUtils.displayNameForURL(targetInfo.url as Platform.DevToolsPath.UrlString);
}
return target.targetInfo()?.subtype || '';
}
isItemSelectable(_item: SDK.Target.Target): boolean {
return true;
}
itemSelected(item: SDK.Target.Target|null): void {
const title =
item ? i18nString(UIStrings.targetS, {PH1: this.titleFor(item)}) : i18nString(UIStrings.targetNotSelected);
this.#toolbarItem.setTitle(title);
if (item && item !== UI.Context.Context.instance().flavor(SDK.Target.Target)?.outermostTarget()) {
UI.Context.Context.instance().setFlavor(SDK.Target.Target, item);
}
}
}