Skip to content

Commit

Permalink
Move Reconnect DevTools toolbar button to own module (#140)
Browse files Browse the repository at this point in the history
  • Loading branch information
huntie authored Dec 2, 2024
1 parent 8831e78 commit 72b8929
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 75 deletions.
1 change: 1 addition & 0 deletions config/gni/devtools_grd_files.gni
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions front_end/entrypoints/rn_fusebox/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import("../visibility.gni")

devtools_module("rn_fusebox") {
sources = [
"FuseboxReconnectDeviceButton.ts",
"FuseboxProfilingBuildObserver.ts",
]

Expand Down
89 changes: 89 additions & 0 deletions front_end/entrypoints/rn_fusebox/FuseboxReconnectDeviceButton.ts
Original file line number Diff line number Diff line change
@@ -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;
}
}
84 changes: 9 additions & 75 deletions front_end/entrypoints/rn_fusebox/rn_fusebox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'));
Expand All @@ -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_);
Expand Down Expand Up @@ -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;
},
Expand All @@ -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();
},
});

Expand Down

0 comments on commit 72b8929

Please sign in to comment.