2021-12-10 02:37:01 +00:00
|
|
|
/**
|
|
|
|
|
* @license
|
|
|
|
|
* Copyright Google LLC All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by an MIT-style license that can be
|
2024-09-20 15:23:15 +00:00
|
|
|
* found in the LICENSE file at https://angular.dev/license
|
2021-12-10 02:37:01 +00:00
|
|
|
*/
|
|
|
|
|
|
2024-07-30 07:25:46 +00:00
|
|
|
import {Component, computed, inject, input, output, signal} from '@angular/core';
|
2024-01-19 21:52:14 +00:00
|
|
|
import {MatIcon} from '@angular/material/icon';
|
|
|
|
|
import {MatMenu, MatMenuItem, MatMenuTrigger} from '@angular/material/menu';
|
|
|
|
|
import {MatSlideToggle} from '@angular/material/slide-toggle';
|
|
|
|
|
import {MatTabLink, MatTabNav, MatTabNavPanel} from '@angular/material/tabs';
|
|
|
|
|
import {MatTooltip} from '@angular/material/tooltip';
|
2021-12-09 05:44:17 +00:00
|
|
|
import {Events, MessageBus, Route} from 'protocol';
|
|
|
|
|
|
2024-03-05 03:55:01 +00:00
|
|
|
import {ApplicationEnvironment, Frame, TOP_LEVEL_FRAME_ID} from '../application-environment/index';
|
|
|
|
|
import {FrameManager} from '../frame_manager';
|
2021-12-09 05:44:17 +00:00
|
|
|
import {Theme, ThemeService} from '../theme-service';
|
|
|
|
|
|
|
|
|
|
import {DirectiveExplorerComponent} from './directive-explorer/directive-explorer.component';
|
2024-01-19 21:52:14 +00:00
|
|
|
import {InjectorTreeComponent} from './injector-tree/injector-tree.component';
|
|
|
|
|
import {ProfilerComponent} from './profiler/profiler.component';
|
|
|
|
|
import {RouterTreeComponent} from './router-tree/router-tree.component';
|
2021-12-09 05:44:17 +00:00
|
|
|
import {TabUpdate} from './tab-update/index';
|
2020-01-27 18:40:18 +00:00
|
|
|
|
2024-01-16 21:35:47 +00:00
|
|
|
type Tabs = 'Components' | 'Profiler' | 'Router Tree' | 'Injector Tree';
|
2023-12-04 21:19:43 +00:00
|
|
|
|
2020-01-27 18:40:18 +00:00
|
|
|
@Component({
|
|
|
|
|
selector: 'ng-devtools-tabs',
|
|
|
|
|
templateUrl: './devtools-tabs.component.html',
|
2020-03-29 03:28:36 +00:00
|
|
|
styleUrls: ['./devtools-tabs.component.scss'],
|
2024-01-19 21:52:14 +00:00
|
|
|
standalone: true,
|
|
|
|
|
imports: [
|
|
|
|
|
MatTabNav,
|
|
|
|
|
MatTabNavPanel,
|
|
|
|
|
MatTooltip,
|
|
|
|
|
MatIcon,
|
|
|
|
|
MatMenu,
|
|
|
|
|
MatMenuItem,
|
|
|
|
|
MatMenuTrigger,
|
|
|
|
|
MatTabLink,
|
|
|
|
|
DirectiveExplorerComponent,
|
|
|
|
|
ProfilerComponent,
|
|
|
|
|
RouterTreeComponent,
|
|
|
|
|
InjectorTreeComponent,
|
|
|
|
|
MatSlideToggle,
|
|
|
|
|
],
|
|
|
|
|
providers: [TabUpdate],
|
2020-01-27 18:40:18 +00:00
|
|
|
})
|
2024-07-30 07:25:46 +00:00
|
|
|
export class DevToolsTabsComponent {
|
|
|
|
|
readonly isHydrationEnabled = input(false);
|
|
|
|
|
readonly frameSelected = output<Frame>();
|
2020-08-08 20:43:42 +00:00
|
|
|
|
2024-07-30 07:25:46 +00:00
|
|
|
readonly applicationEnvironment = inject(ApplicationEnvironment);
|
|
|
|
|
readonly activeTab = signal<Tabs>('Components');
|
|
|
|
|
readonly inspectorRunning = signal(false);
|
|
|
|
|
readonly showCommentNodes = signal(false);
|
|
|
|
|
readonly timingAPIEnabled = signal(false);
|
2024-01-26 00:35:36 +00:00
|
|
|
|
2024-07-30 07:25:46 +00:00
|
|
|
readonly routes = signal<Route[]>([]);
|
|
|
|
|
readonly frameManager = inject(FrameManager);
|
|
|
|
|
|
|
|
|
|
readonly tabs = computed<Tabs[]>(() => {
|
|
|
|
|
const alwaysShown: Tabs[] = ['Components', 'Profiler', 'Injector Tree'];
|
|
|
|
|
return this.routes().length === 0 ? alwaysShown : [...alwaysShown, 'Router Tree'];
|
|
|
|
|
});
|
2024-03-05 03:55:01 +00:00
|
|
|
|
2024-07-30 07:25:46 +00:00
|
|
|
profilingNotificationsSupported = Boolean(
|
|
|
|
|
(window.chrome?.devtools as any)?.performance?.onProfilingStarted,
|
|
|
|
|
);
|
2024-03-05 03:55:01 +00:00
|
|
|
TOP_LEVEL_FRAME_ID = TOP_LEVEL_FRAME_ID;
|
|
|
|
|
|
2024-07-30 07:25:46 +00:00
|
|
|
readonly angularVersion = input<string | undefined>(undefined);
|
|
|
|
|
readonly majorAngularVersion = computed(() => {
|
2024-04-05 22:24:43 +00:00
|
|
|
const version = this.angularVersion();
|
|
|
|
|
if (!version) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return parseInt(version.toString().split('.')[0], 10);
|
|
|
|
|
});
|
|
|
|
|
|
2024-07-30 07:25:46 +00:00
|
|
|
readonly extensionVersion = signal('Development Build');
|
2024-05-06 20:16:22 +00:00
|
|
|
|
2024-07-30 07:25:46 +00:00
|
|
|
public tabUpdate = inject(TabUpdate);
|
|
|
|
|
public themeService = inject(ThemeService);
|
|
|
|
|
private _messageBus = inject<MessageBus<Events>>(MessageBus);
|
2021-03-11 05:41:50 +00:00
|
|
|
|
2024-07-30 07:25:46 +00:00
|
|
|
constructor() {
|
2021-03-11 05:41:50 +00:00
|
|
|
this._messageBus.on('updateRouterTree', (routes) => {
|
2024-07-30 07:25:46 +00:00
|
|
|
this.routes.set(routes || []);
|
2021-03-11 05:41:50 +00:00
|
|
|
});
|
2023-08-30 22:41:16 +00:00
|
|
|
|
2024-07-30 07:25:46 +00:00
|
|
|
if (typeof chrome !== 'undefined' && chrome.runtime !== undefined) {
|
|
|
|
|
this.extensionVersion.set(chrome.runtime.getManifest().version);
|
2024-05-06 20:16:22 +00:00
|
|
|
}
|
2021-03-11 05:41:50 +00:00
|
|
|
}
|
|
|
|
|
|
2024-07-30 07:25:46 +00:00
|
|
|
emitSelectedFrame(frameId: string): void {
|
|
|
|
|
const frame = this.frameManager.frames.find((frame) => frame.id === parseInt(frameId, 10));
|
|
|
|
|
this.frameSelected.emit(frame!);
|
2021-02-13 10:22:04 +00:00
|
|
|
}
|
|
|
|
|
|
2023-12-04 21:19:43 +00:00
|
|
|
changeTab(tab: Tabs): void {
|
2024-07-30 07:25:46 +00:00
|
|
|
this.activeTab.set(tab);
|
2024-08-28 06:08:31 +00:00
|
|
|
this.tabUpdate.notify(tab);
|
2021-02-07 13:15:42 +00:00
|
|
|
if (tab === 'Router Tree') {
|
2021-03-04 04:43:18 +00:00
|
|
|
this._messageBus.emit('getRoutes');
|
2021-02-07 13:15:42 +00:00
|
|
|
}
|
2021-02-13 10:22:04 +00:00
|
|
|
}
|
|
|
|
|
|
2020-01-29 00:29:23 +00:00
|
|
|
toggleInspector(): void {
|
2020-02-06 22:41:19 +00:00
|
|
|
this.toggleInspectorState();
|
|
|
|
|
this.emitInspectorEvent();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
emitInspectorEvent(): void {
|
2024-07-30 07:25:46 +00:00
|
|
|
if (this.inspectorRunning()) {
|
2020-03-18 00:48:29 +00:00
|
|
|
this._messageBus.emit('inspectorStart');
|
2020-01-27 18:40:18 +00:00
|
|
|
} else {
|
2020-03-18 00:48:29 +00:00
|
|
|
this._messageBus.emit('inspectorEnd');
|
2020-04-14 22:27:59 +00:00
|
|
|
this._messageBus.emit('removeHighlightOverlay');
|
2020-01-27 18:40:18 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-06 22:41:19 +00:00
|
|
|
toggleInspectorState(): void {
|
2024-07-30 07:25:46 +00:00
|
|
|
this.inspectorRunning.update((state) => !state);
|
2020-02-06 22:41:19 +00:00
|
|
|
}
|
|
|
|
|
|
2023-08-30 22:41:16 +00:00
|
|
|
toggleTimingAPI(): void {
|
2024-07-30 07:25:46 +00:00
|
|
|
this.timingAPIEnabled.update((state) => !state);
|
|
|
|
|
this.timingAPIEnabled()
|
2024-01-16 21:35:47 +00:00
|
|
|
? this._messageBus.emit('enableTimingAPI')
|
|
|
|
|
: this._messageBus.emit('disableTimingAPI');
|
2020-05-07 03:21:32 +00:00
|
|
|
}
|
2020-01-27 18:40:18 +00:00
|
|
|
}
|