diff --git a/front_end/global_typings/react_native.d.ts b/front_end/global_typings/react_native.d.ts
index bfbc9b23fd3..c4251df3c96 100644
--- a/front_end/global_typings/react_native.d.ts
+++ b/front_end/global_typings/react_native.d.ts
@@ -10,6 +10,7 @@ declare global {
var enableReactNativePerfMetrics: boolean|undefined;
var enableReactNativePerfMetricsGlobalPostMessage: boolean|undefined;
var enableReactNativeOpenInExternalEditor: boolean|undefined;
+ var enableDisplayingFullDisconnectedReason: boolean|undefined;
var reactNativeOpenInEditorButtonImage: string|undefined;
var FB_ONLY__reactNativeFeedbackLink: string|undefined;
var FB_ONLY__enablePerformance: any;
diff --git a/front_end/panels/rn_welcome/RNWelcome.ts b/front_end/panels/rn_welcome/RNWelcome.ts
index 2d6d772d780..17d63994316 100644
--- a/front_end/panels/rn_welcome/RNWelcome.ts
+++ b/front_end/panels/rn_welcome/RNWelcome.ts
@@ -7,6 +7,7 @@ import type * as Common from '../../core/common/common.js';
import * as UI from '../../ui/legacy/legacy.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 SDK from '../../core/sdk/sdk.js';
import rnWelcomeStyles from './rnWelcome.css.js';
@@ -25,6 +26,8 @@ const UIStrings = {
docsLabel: 'Debugging docs',
/** @description "What's new" link */
whatsNewLabel: "What's new",
+ /** @description Description for sharing the session ID of the current session with the user */
+ sessionIdMessage: "[FB-only] The session ID for this React Native DevTools lauch is: ",
/** @description "Debugging Basics" title (docs item 1) */
docsDebuggingBasics: 'Debugging Basics',
/** @description "Debugging Basics" item detail */
@@ -132,6 +135,8 @@ export class RNWelcomeImpl extends UI.Widget.VBox implements
import.meta.url,
).toString();
+ const launchId = Root.Runtime.Runtime.queryParam('launchId');
+
render(html`
@@ -162,6 +167,13 @@ export class RNWelcomeImpl extends UI.Widget.VBox implements
${i18nString(UIStrings.whatsNewLabel)}
+ ${launchId ? html`
+
+ ${i18nString(UIStrings.sessionIdMessage)}
+
+ ${launchId}
+
+ ` : ''}
${this.#reactNativeVersion !== null && this.#reactNativeVersion !== undefined ? html`
React Native: ${this.#reactNativeVersion}
` : null}
diff --git a/front_end/panels/rn_welcome/rnWelcome.css b/front_end/panels/rn_welcome/rnWelcome.css
index 3ff5f3d0be1..d6eef0adda0 100644
--- a/front_end/panels/rn_welcome/rnWelcome.css
+++ b/front_end/panels/rn_welcome/rnWelcome.css
@@ -101,6 +101,13 @@
border-right: 1px solid var(--color-details-hairline);
}
+.rn-session-id {
+ display: flex;
+ align-items: center;
+ margin-top: 24px;
+ user-select: all;
+}
+
.rn-welcome-version {
position: fixed;
top: 8px;
diff --git a/front_end/ui/legacy/RemoteDebuggingTerminatedScreen.ts b/front_end/ui/legacy/RemoteDebuggingTerminatedScreen.ts
index d9f8b74792a..469333e0c38 100644
--- a/front_end/ui/legacy/RemoteDebuggingTerminatedScreen.ts
+++ b/front_end/ui/legacy/RemoteDebuggingTerminatedScreen.ts
@@ -4,6 +4,7 @@
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 type * as Platform from '../../core/platform/platform.js';
import * as LitHtml from '../../ui/lit-html/lit-html.js';
@@ -24,6 +25,12 @@ const UIStrings = {
* (see https://developer.chrome.com/docs/devtools/remote-debugging/).
*/
debuggingConnectionWasClosed: 'Debugging connection was closed. Reason: ',
+ /**
+ * @description Text in a dialog box in DevTools providing extra details on why remote debugging has been terminated.
+ * "Remote debugging" here means that DevTools on a PC is inspecting a website running on an actual mobile device
+ * (see https://developer.chrome.com/docs/devtools/remote-debugging/).
+ */
+ debuggingConnectionWasClosedDetails: 'Details: ',
/**
* @description Text in a dialog box showing how to reconnect to DevTools when remote debugging has been terminated.
* "Remote debugging" here means that DevTools on a PC is inspecting a website running on an actual mobile device
@@ -50,6 +57,11 @@ const UIStrings = {
* @description Text in a dialog box to prompt for feedback if the disconnection is unexpected.
*/
sendFeedbackMessage: '[FB-only] Please send feedback if this disconnection is unexpected.',
+ /**
+ * @description Text in a dialog box to prompt for feedback if the disconnection is unexpected,
+ * telling the user what's their session ID for easier debugging
+ */
+ sendFeedbackLaunchIdMessage: 'Please include the following session ID:',
/**
* @description Label of the FB-only 'send feedback' button.
*/
@@ -62,7 +74,11 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
const {render, html} = LitHtml;
export class RemoteDebuggingTerminatedScreen extends VBox {
- constructor(reason: string, onClose?: () => void) {
+ constructor(
+ reason: string,
+ connectionLostDetails?: {reason?: string, code?: string, errorType?: string},
+ onClose?: () => void
+ ) {
super(true);
this.registerCSSFiles([remoteDebuggingTerminatedScreenStyles]);
@@ -75,19 +91,28 @@ export class RemoteDebuggingTerminatedScreen extends VBox {
html`
${i18nString(UIStrings.title)}
-
${i18nString(UIStrings.debuggingConnectionWasClosed)}
-
${reason}
+
${i18nString(UIStrings.debuggingConnectionWasClosed)}
+
${reason}
+ ${globalThis.enableDisplayingFullDisconnectedReason ?
+ html`
+
+ ${i18nString(UIStrings.debuggingConnectionWasClosedDetails)}
+
+
+
+
+ ` : ''}
+ ${feedbackLink !== null && feedbackLink !== undefined ? this.#createFeedbackSection(feedbackLink) : null}
${i18nString(UIStrings.reconnectWhenReadyByReopening)}
- ${
- createTextButton(
- i18nString(UIStrings.reconnectDevtools),
- handleReconnect,
- {className: 'primary-button', jslogContext: 'reconnect'},
- )}
+ ${createTextButton(
+ i18nString(UIStrings.reconnectDevtools),
+ handleReconnect,
+ {className: 'primary-button', jslogContext: 'reconnect'},
+ )}
${i18nString(UIStrings.closeDialogDetail)}
@@ -95,7 +120,6 @@ export class RemoteDebuggingTerminatedScreen extends VBox {
jslogContext: 'dismiss',
})}
- ${feedbackLink !== null && feedbackLink !== undefined ? this.#createFeedbackSection(feedbackLink) : null}
`,
this.contentElement,
{host: this},
@@ -109,7 +133,7 @@ export class RemoteDebuggingTerminatedScreen extends VBox {
const dialog = new Dialog('remote-debnugging-terminated');
dialog.setSizeBehavior(SizeBehavior.MeasureContent);
dialog.setDimmed(true);
- new RemoteDebuggingTerminatedScreen(uiMessage, () => dialog.hide()).show(dialog.contentElement);
+ new RemoteDebuggingTerminatedScreen(uiMessage, connectionLostDetails, () => dialog.hide()).show(dialog.contentElement);
dialog.show();
Host.rnPerfMetrics.remoteDebuggingTerminated(connectionLostDetails);
}
@@ -121,9 +145,22 @@ export class RemoteDebuggingTerminatedScreen extends VBox {
);
};
+ const launchId = Root.Runtime.Runtime.queryParam('launchId');
+
return html`
${i18nString(UIStrings.sendFeedbackMessage)}
+ ${launchId ?
+ html`
+
+ ${i18nString(UIStrings.sendFeedbackLaunchIdMessage)}
+
+
+ ${launchId}
+
+ ` : ''
+ }
+
${
createTextButton(
i18nString(UIStrings.sendFeedback),
diff --git a/front_end/ui/legacy/components/utils/TargetDetachedDialog.ts b/front_end/ui/legacy/components/utils/TargetDetachedDialog.ts
index da499434aff..ab66d6949b7 100644
--- a/front_end/ui/legacy/components/utils/TargetDetachedDialog.ts
+++ b/front_end/ui/legacy/components/utils/TargetDetachedDialog.ts
@@ -13,7 +13,21 @@ const UIStrings = {
*@description Text on the remote debugging window to indicate the connection is lost
*/
websocketDisconnected: 'WebSocket disconnected',
+ /**
+ *@description Text on the remote debugging window to indicate the connection cannot be made because the device is not connected
+ */
+ websocketDisconnectedUnregisteredDevice: 'The corresponding app for this DevTools session cannot be found. Please relaunch DevTools from the terminal.',
+ /**
+ *@description Text on the remote debugging window to indicate the connection to corresponding device was lost
+ */
+ websocketDisconnectedConnectionLost: 'Connection lost to corresponding device'
};
+
+const DisconnectedReasonsUIStrings = {
+ UREGISTERED_DEVICE: UIStrings.websocketDisconnectedUnregisteredDevice,
+ CONNECTION_LOST: UIStrings.websocketDisconnectedConnectionLost
+}
+
const str_ = i18n.i18n.registerUIStrings('ui/legacy/components/utils/TargetDetachedDialog.ts', UIStrings);
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
export class TargetDetachedDialog extends SDK.SDKModel.SDKModel
implements ProtocolProxyApi.InspectorDispatcher {
@@ -33,9 +47,25 @@ export class TargetDetachedDialog extends SDK.SDKModel.SDKModel implements
UI.RemoteDebuggingTerminatedScreen.RemoteDebuggingTerminatedScreen.show(reason);
}
+ static getCustomUiReason(connectionLostDetails?: {reason?: string, code?: string, errorType?: string}): string | null {
+ if (!connectionLostDetails) {
+ return null;
+ }
+
+ if (connectionLostDetails.code === "1011" && connectionLostDetails.reason?.includes('[UREGISTERED_DEVICE]')) {
+ return i18nString(DisconnectedReasonsUIStrings.UREGISTERED_DEVICE);
+ }
+
+ if (connectionLostDetails.code === "1000" && connectionLostDetails.reason?.includes('[CONNECTION_LOST]')) {
+ return i18nString(DisconnectedReasonsUIStrings.CONNECTION_LOST);
+ }
+
+ return null;
+ }
+
static webSocketConnectionLost(connectionLostDetails?: {reason?: string, code?: string, errorType?: string}): void {
- UI.RemoteDebuggingTerminatedScreen.RemoteDebuggingTerminatedScreen.show(
- i18nString(UIStrings.websocketDisconnected), connectionLostDetails);
+ const uiReason = TargetDetachedDialog.getCustomUiReason(connectionLostDetails) || i18nString(UIStrings.websocketDisconnected);
+ UI.RemoteDebuggingTerminatedScreen.RemoteDebuggingTerminatedScreen.show(uiReason, connectionLostDetails);
}
targetCrashed(): void {
diff --git a/front_end/ui/legacy/remoteDebuggingTerminatedScreen.css b/front_end/ui/legacy/remoteDebuggingTerminatedScreen.css
index 02a5ef703a9..aa5d976704c 100644
--- a/front_end/ui/legacy/remoteDebuggingTerminatedScreen.css
+++ b/front_end/ui/legacy/remoteDebuggingTerminatedScreen.css
@@ -6,6 +6,7 @@
.widget {
padding: 20px;
+ user-select: text;
}
.remote-debugging-terminated-title {
@@ -17,7 +18,7 @@
.remote-debugging-terminated-message {
font-size: 14px;
margin: 5px 0;
- margin-bottom: 24px;
+ margin-bottom: 16px;
}
.remote-debugging-terminated-options {
@@ -25,8 +26,6 @@
grid-template-columns: 1fr auto;
grid-gap: 8px;
align-items: center;
- padding-top: 12px;
- border-top: 1px solid var(--color-details-hairline-light);
}
.remote-debugging-terminated-label {
@@ -45,10 +44,10 @@
display: flex;
flex-direction: column;
align-items: center;
- margin-top: 16px;
padding: 12px 16px;
background-color: var(--color-background-elevation-1);
border-radius: 6px;
+ margin-bottom: 12px;
}
.remote-debugging-terminated-feedback-label {
@@ -56,10 +55,17 @@
margin-bottom: 8px;
}
-.remote-debugging-terminated-reason {
- --override-reason-color: #8b0000;
+.remote-debugging-terminated-feedback-launch-id {
+ color: red;
+}
+.remote-debugging-terminated-reason {
+ --override-reason-color: red;
color: var(--override-reason-color);
+ margin: 8px;
+ textarea {
+ width: 100%;
+ }
}
.theme-with-dark-background .reason,