UNPKG

chrome-devtools-frontend

Version:
140 lines (125 loc) 4.61 kB
// Copyright 2019 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import '../../ui/legacy/components/data_grid/data_grid.js'; import * as i18n from '../../core/i18n/i18n.js'; import * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js'; import * as UI from '../../ui/legacy/legacy.js'; import {Directives, html, render} from '../../ui/lit/lit.js'; import * as VisualLogging from '../../ui/visual_logging/visual_logging.js'; import eventDisplayTableStyles from './eventDisplayTable.css.js'; import type {PlayerEvent} from './MediaModel.js'; const {widget} = UI.Widget; const {repeat} = Directives; const UIStrings = { /** * @description Text for timestamps of items. */ timestamp: 'Timestamp', /** * @description The column header for event names. */ eventName: 'Event name', /** * @description Text for the value of something. */ value: 'Value', /** * @description The accessible name of a table that displays information about events that occurred * while a video/media player was present on the page. */ eventDisplay: 'Event display', } as const; const str_ = i18n.i18n.registerUIStrings('panels/media/EventDisplayTable.ts', UIStrings); const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export interface EventDisplayRow { displayTimestamp: string; event: string; value: Record<string, unknown>; } export interface PlayerEventsViewInput { parsedEvents: EventDisplayRow[]; } export type View = (input: PlayerEventsViewInput, output: void, target: HTMLElement) => void; export const DEFAULT_VIEW: View = (input, _output, target) => { // clang-format off render(html` <style>${eventDisplayTableStyles}</style> <devtools-data-grid row-height='auto' autoscroll striped name=${i18nString(UIStrings.eventDisplay)} class="event-display-table-contents-table-container no-border-top-datagrid" .template=${html` <style>${eventDisplayTableStyles}</style> <table> <thead> <tr> <th id="display-timestamp" weight="1">${i18nString(UIStrings.timestamp)}</th> <th id="event" weight="2">${i18nString(UIStrings.eventName)}</th> <th id="value" weight="7">${i18nString(UIStrings.value)}</th> </tr> </thead> <tbody> ${repeat(input.parsedEvents, event => event, event => html` <tr> <td class="event-display-table-basic-text-table-entry">${event.displayTimestamp}</td> <td class="event-display-table-basic-text-table-entry">${event.event}</td> <td class="event-display-table-contents-json-wrapper"> ${widget(el => new SourceFrame.JSONView.JSONView(new SourceFrame.JSONView.ParsedJSON(event.value, '', ''), true, el))} </td> </tr> `)} </tbody> </table> `}> </devtools-data-grid> `, // clang-format on target); }; export class PlayerEventsView extends UI.Widget.VBox { private firstEventTime: number; #view: View; #parsedEvents: EventDisplayRow[] = []; constructor(view: View = DEFAULT_VIEW) { super({jslog: `${VisualLogging.pane('events')}`}); this.#view = view; this.firstEventTime = 0; this.requestUpdate(); } override wasShown(): void { super.wasShown(); this.requestUpdate(); } override performUpdate(): void { const viewInput = { parsedEvents: this.#parsedEvents, }; this.#view(viewInput, undefined, this.contentElement); } onEvent(event: PlayerEvent): void { if (this.firstEventTime === 0 && typeof event.timestamp === 'number') { this.firstEventTime = event.timestamp; } event = this.subtractFirstEventTime(event); const stringified = event.value; try { const json = JSON.parse(stringified); event.event = json.event; delete json['event']; this.#parsedEvents.push({ displayTimestamp: event.displayTimestamp, event: event.event, value: json, }); this.requestUpdate(); } catch { // If this is a legacy message event, ignore it for now until they // are handled. } } private subtractFirstEventTime(event: PlayerEvent): PlayerEvent { if (typeof event.timestamp === 'number') { event.displayTimestamp = (event.timestamp - this.firstEventTime).toFixed(3); } return event; } }