From 72b89295a85acb50e0b775a1e677cf2737ee70a4 Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Mon, 2 Dec 2024 12:08:06 +0000 Subject: [PATCH] Move Reconnect DevTools toolbar button to own module (#140) --- config/gni/devtools_grd_files.gni | 1 + front_end/entrypoints/rn_fusebox/BUILD.gn | 1 + .../FuseboxReconnectDeviceButton.ts | 89 +++++++++++++++++++ .../entrypoints/rn_fusebox/rn_fusebox.ts | 84 ++--------------- 4 files changed, 100 insertions(+), 75 deletions(-) create mode 100644 front_end/entrypoints/rn_fusebox/FuseboxReconnectDeviceButton.ts diff --git a/config/gni/devtools_grd_files.gni b/config/gni/devtools_grd_files.gni index 1a02f0e72a7..0e034586bdc 100644 --- a/config/gni/devtools_grd_files.gni +++ b/config/gni/devtools_grd_files.gni @@ -843,6 +843,7 @@ grd_files_debug_sources = [ "front_end/entrypoints/node_app/NodeMain.js", "front_end/entrypoints/node_app/nodeConnectionsPanel.css.js", "front_end/entrypoints/rn_fusebox/FuseboxProfilingBuildObserver.js", + "front_end/entrypoints/rn_fusebox/FuseboxReconnectDeviceButton.js", "front_end/entrypoints/shell/browser_compatibility_guard.js", "front_end/entrypoints/wasmparser_worker/WasmParserWorker.js", "front_end/entrypoints/worker_app/WorkerMain.js", diff --git a/front_end/entrypoints/rn_fusebox/BUILD.gn b/front_end/entrypoints/rn_fusebox/BUILD.gn index 5034fe7ae30..038049032cf 100644 --- a/front_end/entrypoints/rn_fusebox/BUILD.gn +++ b/front_end/entrypoints/rn_fusebox/BUILD.gn @@ -9,6 +9,7 @@ import("../visibility.gni") devtools_module("rn_fusebox") { sources = [ + "FuseboxReconnectDeviceButton.ts", "FuseboxProfilingBuildObserver.ts", ] diff --git a/front_end/entrypoints/rn_fusebox/FuseboxReconnectDeviceButton.ts b/front_end/entrypoints/rn_fusebox/FuseboxReconnectDeviceButton.ts new file mode 100644 index 00000000000..78ef8f179be --- /dev/null +++ b/front_end/entrypoints/rn_fusebox/FuseboxReconnectDeviceButton.ts @@ -0,0 +1,89 @@ +// 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 Common from '../../core/common/common.js'; +import * as i18n from '../../core/i18n/i18n.js'; +import * as SDK from '../../core/sdk/sdk.js'; +import * as Protocol from '../../generated/protocol.js'; +import * as UI from '../../ui/legacy/legacy.js'; + +const UIStrings = { + /** + *@description Tooltip of the connection status toolbar button while disconnected + */ + connectionStatusDisconnectedTooltip: 'Debugging connection was closed', + /** + *@description Button label of the connection status toolbar button while disconnected + */ + connectionStatusDisconnectedLabel: 'Reconnect DevTools', +}; +const str_ = i18n.i18n.registerUIStrings('entrypoints/rn_fusebox/ConnectionStatusToolbarItem.ts', UIStrings); +const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_); + +let connectionStatusIndicatorInstance: FuseboxReconnectDeviceButton; + +export default class FuseboxReconnectDeviceButton extends SDK.TargetManager.Observer implements + UI.Toolbar.Provider { + #button = new UI.Toolbar.ToolbarButton(''); + + private constructor() { + super(); + this.#button.setVisible(false); + this.#button.element.classList.add('fusebox-connection-status'); + this.#button.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, this.#handleClick.bind(this)); + + SDK.TargetManager.TargetManager.instance().observeTargets(this, {scoped: true}); + } + + static instance(): FuseboxReconnectDeviceButton { + if (!connectionStatusIndicatorInstance) { + connectionStatusIndicatorInstance = new FuseboxReconnectDeviceButton(); + } + return connectionStatusIndicatorInstance; + } + + override targetAdded(target: SDK.Target.Target): void { + this.#onTargetChanged(target); + } + + override targetRemoved(target: SDK.Target.Target): void { + this.#onTargetChanged(target); + } + + #onTargetChanged(target: SDK.Target.Target): void { + const rootTarget = SDK.TargetManager.TargetManager.instance().rootTarget(); + this.#button.setTitle(i18nLazyString(UIStrings.connectionStatusDisconnectedTooltip)()); + this.#button.setText(i18nLazyString(UIStrings.connectionStatusDisconnectedLabel)()); + this.#button.setVisible(!rootTarget); + + if (!rootTarget) { + this.#printPreserveLogPrompt(target); + } + } + + #printPreserveLogPrompt(target: SDK.Target.Target): void { + if (Common.Settings.Settings.instance().moduleSetting('preserve-console-log').get()) { + return; + } + + target.model(SDK.ConsoleModel.ConsoleModel) + ?.addMessage(new SDK.ConsoleModel.ConsoleMessage( + target.model(SDK.RuntimeModel.RuntimeModel), Protocol.Log.LogEntrySource.Recommendation, + Protocol.Log.LogEntryLevel.Info, + '[React Native] Console messages are currently cleared upon DevTools disconnection. You can preserve logs in settings: ', + { + type: SDK.ConsoleModel.FrontendMessageType.System, + context: 'fusebox_preserve_log_rec', + })); + } + + #handleClick(): void { + window.location.reload(); + } + + item(): UI.Toolbar.ToolbarItem { + return this.#button; + } +} diff --git a/front_end/entrypoints/rn_fusebox/rn_fusebox.ts b/front_end/entrypoints/rn_fusebox/rn_fusebox.ts index 30bf19cbfbe..8fcaceac274 100644 --- a/front_end/entrypoints/rn_fusebox/rn_fusebox.ts +++ b/front_end/entrypoints/rn_fusebox/rn_fusebox.ts @@ -19,21 +19,20 @@ import '../../panels/timeline/timeline-meta.js'; import * as Host from '../../core/host/host.js'; import * as i18n from '../../core/i18n/i18n.js'; import * as Root from '../../core/root/root.js'; +import * as RNExperiments from '../../core/rn_experiments/rn_experiments.js'; import * as SDK from '../../core/sdk/sdk.js'; import * as UI from '../../ui/legacy/legacy.js'; import * as Main from '../main/main.js'; import * as Common from '../../core/common/common.js'; import * as Protocol from '../../generated/protocol.js'; +import FuseboxReconnectDeviceButton from './FuseboxReconnectDeviceButton.js'; +import FuseboxProfilingBuildObserver from './FuseboxProfilingBuildObserver.js'; import type * as Platform from '../../core/platform/platform.js'; import type * as Sources from '../../panels/sources/sources.js'; -import * as RNExperiments from '../../core/rn_experiments/rn_experiments.js'; -import FuseboxProfilingBuildObserver from './FuseboxProfilingBuildObserver.js'; -/* - * To ensure accurate timing measurements, - * please make sure these perf metrics lines are called ahead of everything else - */ +// To ensure accurate timing measurements, please make sure these perf metrics +// lines are called ahead of everything else Host.rnPerfMetrics.registerPerfMetricsGlobalPostMessageHandler(); Host.rnPerfMetrics.registerGlobalErrorReporting(); Host.rnPerfMetrics.setLaunchId(Root.Runtime.Runtime.queryParam('launchId')); @@ -52,14 +51,6 @@ const UIStrings = { *@description Label of the FB-only 'send feedback' action button in the toolbar */ sendFeedback: '[FB-only] Send feedback', - /** - *@description Tooltip of the connection status toolbar button while disconnected - */ - connectionStatusDisconnectedTooltip: 'Debugging connection was closed', - /** - *@description Button label of the connection status toolbar button while disconnected - */ - connectionStatusDisconnectedLabel: 'Reconnect DevTools', }; const str_ = i18n.i18n.registerUIStrings('entrypoints/rn_fusebox/rn_fusebox.ts', UIStrings); const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_); @@ -141,9 +132,9 @@ if (globalThis.FB_ONLY__reactNativeFeedbackLink) { if (incomingActionId !== actionId) { return false; } - Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab( - feedbackLink, - ); + Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab( + feedbackLink, + ); return true; }, @@ -166,67 +157,10 @@ if (globalThis.FB_ONLY__reactNativeFeedbackLink) { }); } -class ConnectionStatusToolbarItemProvider extends SDK.TargetManager.Observer implements UI.Toolbar.Provider { - #button = new UI.Toolbar.ToolbarButton(''); - - constructor() { - super(); - this.#button.setVisible(false); - this.#button.element.classList.add('fusebox-connection-status'); - this.#button.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, this.onClick.bind(this)); - - SDK.TargetManager.TargetManager.instance().observeTargets(this, {scoped: true}); - } - - override targetAdded(target: SDK.Target.Target): void { - this.#onTargetChanged(target); - } - - override targetRemoved(target: SDK.Target.Target): void { - this.#onTargetChanged(target); - } - - #onTargetChanged(target: SDK.Target.Target): void { - const rootTarget = SDK.TargetManager.TargetManager.instance().rootTarget(); - this.#button.setTitle(i18nLazyString(UIStrings.connectionStatusDisconnectedTooltip)()); - this.#button.setText(i18nLazyString(UIStrings.connectionStatusDisconnectedLabel)()); - this.#button.setVisible(!rootTarget); - - if (!rootTarget) { - this.#printPreserveLogPrompt(target); - } - } - - #printPreserveLogPrompt(target: SDK.Target.Target): void { - if (Common.Settings.Settings.instance().moduleSetting('preserve-console-log').get()) { - return; - } - - target.model(SDK.ConsoleModel.ConsoleModel) - ?.addMessage(new SDK.ConsoleModel.ConsoleMessage( - target.model(SDK.RuntimeModel.RuntimeModel), Protocol.Log.LogEntrySource.Recommendation, - Protocol.Log.LogEntryLevel.Info, - '[React Native] Console messages are currently cleared upon DevTools disconnection. You can preserve logs in settings: ', - { - type: SDK.ConsoleModel.FrontendMessageType.System, - context: 'fusebox_preserve_log_rec', - })); - } - - onClick(): void { - window.location.reload(); - } - - item(): UI.Toolbar.ToolbarItem { - return this.#button; - } -} - -const connectionStatusToolbarItemProvider = new ConnectionStatusToolbarItemProvider(); UI.Toolbar.registerToolbarItem({ location: UI.Toolbar.ToolbarItemLocation.MAIN_TOOLBAR_RIGHT, loadItem: async () => { - return connectionStatusToolbarItemProvider; + return FuseboxReconnectDeviceButton.instance(); }, });