diff --git a/config/gni/devtools_grd_files.gni b/config/gni/devtools_grd_files.gni index bd55de2bf82..a8a752bc3fe 100644 --- a/config/gni/devtools_grd_files.gni +++ b/config/gni/devtools_grd_files.gni @@ -1899,6 +1899,7 @@ grd_files_debug_sources = [ "front_end/panels/timeline/LayoutShiftsTrackAppender.js", "front_end/panels/timeline/ModificationsManager.js", "front_end/panels/timeline/NetworkTrackAppender.js", + "front_end/panels/timeline/ReactNativeTimelineLandingPage.js", "front_end/panels/timeline/SaveFileFormatter.js", "front_end/panels/timeline/TargetForEvent.js", "front_end/panels/timeline/ThirdPartyTreeView.js", diff --git a/front_end/panels/timeline/BUILD.gn b/front_end/panels/timeline/BUILD.gn index 935b62ad66e..a05cb31fbc4 100644 --- a/front_end/panels/timeline/BUILD.gn +++ b/front_end/panels/timeline/BUILD.gn @@ -72,6 +72,7 @@ devtools_module("timeline") { "LayoutShiftsTrackAppender.ts", "ModificationsManager.ts", "NetworkTrackAppender.ts", + "ReactNativeTimelineLandingPage.ts", "SaveFileFormatter.ts", "TargetForEvent.ts", "ThirdPartyTreeView.ts", diff --git a/front_end/panels/timeline/ReactNativeTimelineLandingPage.ts b/front_end/panels/timeline/ReactNativeTimelineLandingPage.ts new file mode 100644 index 00000000000..d7023f9dd0b --- /dev/null +++ b/front_end/panels/timeline/ReactNativeTimelineLandingPage.ts @@ -0,0 +1,76 @@ +// Copyright (c) Meta Platforms, Inc. and affiliates. +// Copyright 2024 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 i18n from '../../core/i18n/i18n.js'; +import * as UI from '../../ui/legacy/legacy.js'; + +const UIStrings = { + /** + * @description Text for an option to learn more about something + */ + learnmore: 'Learn more', + /** + * @description Text in Timeline Panel of the Performance panel + */ + wasd: 'WASD', + /** + * @description Text in Timeline Panel of the Performance panel + * @example {record} PH1 + * @example {Ctrl + R} PH2 + */ + clickTheRecordButtonSOrHitSTo: 'Click the record button {PH1} or hit {PH2} to start a new recording.', + /** + * @description Text in Timeline Panel of the Performance panel + * @example {Ctrl + U} PH1 + * @example {Learn more} PH2 + */ + afterRecordingSelectAnAreaOf: + 'After recording, select an area of interest in the overview by dragging. Then, zoom and pan the timeline with the mousewheel or {PH1} keys. {PH2}', +} as const; + +const str_ = i18n.i18n.registerUIStrings('panels/timeline/ReactNativeTimelineLandingPage.ts', UIStrings); +const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); + +export class ReactNativeTimelineLandingPage extends UI.Widget.VBox { + private readonly toggleRecordAction: UI.ActionRegistration.Action; + + constructor(toggleRecordAction: UI.ActionRegistration.Action) { + super(); + + this.toggleRecordAction = toggleRecordAction; + + this.contentElement.classList.add('timeline-landing-page', 'fill'); + this.renderLegacyLandingPage(); + } + + private renderLegacyLandingPage(): void { + function encloseWithTag(tagName: string, contents: string): HTMLElement { + const e = document.createElement(tagName); + e.textContent = contents; + return e; + } + + const learnMoreNode = UI.XLink.XLink.create( + 'https://developer.chrome.com/docs/devtools/evaluate-performance/', i18nString(UIStrings.learnmore), undefined, + undefined, 'learn-more'); + + const recordKey = encloseWithTag( + 'b', + UI.ShortcutRegistry.ShortcutRegistry.instance().shortcutsForAction('timeline.toggle-recording')[0].title()); + const navigateNode = encloseWithTag('b', i18nString(UIStrings.wasd)); + + this.contentElement.classList.add('legacy'); + const centered = this.contentElement.createChild('div'); + + const recordButton = UI.UIUtils.createInlineButton(UI.Toolbar.Toolbar.createActionButton(this.toggleRecordAction)); + + centered.createChild('p').appendChild(i18n.i18n.getFormatLocalizedString( + str_, UIStrings.clickTheRecordButtonSOrHitSTo, {PH1: recordButton, PH2: recordKey})); + + centered.createChild('p').appendChild(i18n.i18n.getFormatLocalizedString( + str_, UIStrings.afterRecordingSelectAnAreaOf, {PH1: navigateNode, PH2: learnMoreNode})); + } +} + diff --git a/front_end/panels/timeline/TimelinePanel.ts b/front_end/panels/timeline/TimelinePanel.ts index 64555b15e6f..d56c048c740 100644 --- a/front_end/panels/timeline/TimelinePanel.ts +++ b/front_end/panels/timeline/TimelinePanel.ts @@ -65,6 +65,7 @@ import {Tracker} from './FreshRecording.js'; import {IsolateSelector} from './IsolateSelector.js'; import {AnnotationModifiedEvent, ModificationsManager} from './ModificationsManager.js'; import * as Overlays from './overlays/overlays.js'; +import {ReactNativeTimelineLandingPage} from './ReactNativeTimelineLandingPage.js'; import {cpuprofileJsonGenerator, traceJsonGenerator} from './SaveFileFormatter.js'; import {type Client, TimelineController} from './TimelineController.js'; import {Tab} from './TimelineDetailsView.js'; @@ -2250,9 +2251,13 @@ export class TimelinePanel extends UI.Panel.Panel implements Client, TimelineMod return; } - const liveMetrics = new TimelineComponents.LiveMetricsView.LiveMetricsView(); - liveMetrics.isNode = isNode; - this.landingPage = LegacyWrapper.LegacyWrapper.legacyWrapper(UI.Widget.Widget, liveMetrics); + if (isReactNative) { + this.landingPage = new ReactNativeTimelineLandingPage(this.toggleRecordAction); + } else { + const liveMetrics = new TimelineComponents.LiveMetricsView.LiveMetricsView(); + liveMetrics.isNode = isNode; + this.landingPage = LegacyWrapper.LegacyWrapper.legacyWrapper(UI.Widget.Widget, liveMetrics); + } this.landingPage.element.classList.add('timeline-landing-page', 'fill'); this.landingPage.contentElement.classList.add('fill'); this.landingPage.show(this.statusPaneContainer); diff --git a/scripts/eslint_rules/lib/check-license-header.js b/scripts/eslint_rules/lib/check-license-header.js index 89bda41482d..6ccaffa191d 100644 --- a/scripts/eslint_rules/lib/check-license-header.js +++ b/scripts/eslint_rules/lib/check-license-header.js @@ -85,6 +85,7 @@ const META_CODE_PATHS = [ 'models/react_native', 'panels/react_devtools', 'panels/rn_welcome', + 'panels/timeline/ReactNativeTimelineLandingPage.ts', ]; const OTHER_LICENSE_HEADERS = [