Files
react/packages/react-devtools-shared/src/devtools/views/UnsupportedBridgeProtocolDialog.js
T
Brian Vaughn 8e2bb3e89c DevTools: Add Bridge protocol version backend/frontend (#21331)
Add an explicit Bridge protocol version to the frontend and backend components as well as a check during initialization to ensure that both are compatible. If not, the frontend will display either upgrade or downgrade instructions.

Note that only the `react-devtools-core` (React Native) and `react-devtools-inline` (Code Sandbox) packages implement this check. Browser extensions inject their own backend and so the check is unnecessary. (Arguably the `react-devtools-inline` check is also unlikely to be necessary _but_ has been added as an extra guard for use cases such as Replay.io.)
2021-04-27 17:26:07 -04:00

133 lines
3.9 KiB
JavaScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import * as React from 'react';
import {Fragment, useContext, useEffect} from 'react';
import {ModalDialogContext} from './ModalDialog';
import {StoreContext} from './context';
import {currentBridgeProtocol} from 'react-devtools-shared/src/bridge';
import Button from './Button';
import ButtonIcon from './ButtonIcon';
import {copy} from 'clipboard-js';
import styles from './UnsupportedBridgeProtocolDialog.css';
import type {BridgeProtocol} from 'react-devtools-shared/src/bridge';
const DEVTOOLS_VERSION = process.env.DEVTOOLS_VERSION;
const INSTRUCTIONS_FB_URL = 'https://fburl.com/devtools-bridge-protocol';
export default function UnsupportedBridgeProtocolDialog(_: {||}) {
const {dispatch, isVisible} = useContext(ModalDialogContext);
const store = useContext(StoreContext);
useEffect(() => {
const updateDialog = () => {
if (!isVisible) {
if (store.unsupportedBridgeProtocol !== null) {
dispatch({
canBeDismissed: false,
type: 'SHOW',
content: (
<DialogContent
unsupportedBridgeProtocol={store.unsupportedBridgeProtocol}
/>
),
});
}
} else {
if (store.unsupportedBridgeProtocol === null) {
dispatch({type: 'HIDE'});
}
}
};
updateDialog();
store.addListener('unsupportedBridgeProtocolDetected', updateDialog);
return () => {
store.removeListener('unsupportedBridgeProtocolDetected', updateDialog);
};
}, [isVisible, store]);
return null;
}
function DialogContent({
unsupportedBridgeProtocol,
}: {|
unsupportedBridgeProtocol: BridgeProtocol,
|}) {
const {version, minNpmVersion, maxNpmVersion} = unsupportedBridgeProtocol;
let instructions;
if (maxNpmVersion === null) {
const upgradeInstructions = `npm i -g react-devtools@^${minNpmVersion}`;
instructions = (
<>
<p className={styles.Paragraph}>
To fix this, upgrade the DevTools NPM package:
</p>
<pre className={styles.NpmCommand}>
{upgradeInstructions}
<Button
onClick={() => copy(upgradeInstructions)}
title="Copy upgrade command to clipboard">
<ButtonIcon type="copy" />
</Button>
</pre>
</>
);
} else {
const downgradeInstructions = `npm i -g react-devtools@${maxNpmVersion}`;
instructions = (
<>
<p className={styles.Paragraph}>
To fix this, downgrade the DevTools NPM package:
</p>
<pre className={styles.NpmCommand}>
{downgradeInstructions}
<Button
onClick={() => copy(downgradeInstructions)}
title="Copy downgrade command to clipboard">
<ButtonIcon type="copy" />
</Button>
</pre>
</>
);
}
return (
<Fragment>
<div className={styles.Column}>
<div className={styles.Title}>Unsupported DevTools backend version</div>
<p className={styles.Paragraph}>
You are running <code>react-devtools</code> version{' '}
<span className={styles.Version}>{DEVTOOLS_VERSION}</span>.
</p>
<p className={styles.Paragraph}>
This requires bridge protocol{' '}
<span className={styles.Version}>
version {currentBridgeProtocol.version}
</span>
. However the current backend version uses bridge protocol{' '}
<span className={styles.Version}>version {version}</span>.
</p>
{instructions}
<p className={styles.Paragraph}>
Or{' '}
<a className={styles.Link} href={INSTRUCTIONS_FB_URL} target="_blank">
click here
</a>{' '}
for more information.
</p>
</div>
</Fragment>
);
}