main
js 145 lines 4.43 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 * @flow
8 */
9
10 import * as React from 'react';
11 import {Fragment, useContext, useEffect} from 'react';
12 import {ModalDialogContext} from './ModalDialog';
13 import {StoreContext} from './context';
14 import {currentBridgeProtocol} from 'react-devtools-shared/src/bridge';
15 import Button from './Button';
16 import ButtonIcon from './ButtonIcon';
17 import {copy} from 'clipboard-js';
18 import styles from './UnsupportedBridgeProtocolDialog.css';
19 import {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck';
20
21 import type {BridgeProtocol} from 'react-devtools-shared/src/bridge';
22
23 const DEVTOOLS_VERSION = process.env.DEVTOOLS_VERSION;
24 const INSTRUCTIONS_FB_URL =
25 'https://fb.me/devtools-unsupported-bridge-protocol';
26 const MODAL_DIALOG_ID = 'UnsupportedBridgeProtocolDialog';
27
28 export default function UnsupportedBridgeProtocolDialog(_: {}): null {
29 const {dialogs, dispatch} = useContext(ModalDialogContext);
30 const store = useContext(StoreContext);
31
32 const isVisible = !!dialogs.find(dialog => dialog.id === MODAL_DIALOG_ID);
33
34 useEffect(() => {
35 const updateDialog = () => {
36 if (!isVisible) {
37 if (store.unsupportedBridgeProtocolDetected) {
38 dispatch({
39 canBeDismissed: false,
40 id: MODAL_DIALOG_ID,
41 type: 'SHOW',
42 content: (
43 <DialogContent unsupportedBridgeProtocol={store.bridgeProtocol} />
44 ),
45 });
46 }
47 } else {
48 if (!store.unsupportedBridgeProtocolDetected) {
49 dispatch({
50 type: 'HIDE',
51 id: MODAL_DIALOG_ID,
52 });
53 }
54 }
55 };
56
57 updateDialog();
58
59 store.addListener('unsupportedBridgeProtocolDetected', updateDialog);
60 return () => {
61 store.removeListener('unsupportedBridgeProtocolDetected', updateDialog);
62 };
63 }, [isVisible, store]);
64
65 return null;
66 }
67
68 function DialogContent({
69 unsupportedBridgeProtocol,
70 }: {
71 unsupportedBridgeProtocol: BridgeProtocol,
72 }) {
73 const {version, minNpmVersion, maxNpmVersion} = unsupportedBridgeProtocol;
74
75 let instructions;
76 if (maxNpmVersion === null) {
77 const upgradeInstructions = `npm i -g react-devtools@^${minNpmVersion}`;
78 instructions = (
79 <>
80 <p className={styles.Paragraph}>
81 To fix this, upgrade the DevTools NPM package:
82 </p>
83 <pre className={styles.NpmCommand}>
84 {upgradeInstructions}
85 <Button
86 onClick={withPermissionsCheck(
87 {permissions: ['clipboardWrite']},
88 () => copy(upgradeInstructions),
89 )}
90 title="Copy upgrade command to clipboard">
91 <ButtonIcon type="copy" />
92 </Button>
93 </pre>
94 </>
95 );
96 } else {
97 const downgradeInstructions = `npm i -g react-devtools@${maxNpmVersion}`;
98 instructions = (
99 <>
100 <p className={styles.Paragraph}>
101 To fix this, downgrade the DevTools NPM package:
102 </p>
103 <pre className={styles.NpmCommand}>
104 {downgradeInstructions}
105 <Button
106 onClick={withPermissionsCheck(
107 {permissions: ['clipboardWrite']},
108 () => copy(downgradeInstructions),
109 )}
110 title="Copy downgrade command to clipboard">
111 <ButtonIcon type="copy" />
112 </Button>
113 </pre>
114 </>
115 );
116 }
117
118 return (
119 <Fragment>
120 <div className={styles.Column}>
121 <div className={styles.Title}>Unsupported DevTools backend version</div>
122 <p className={styles.Paragraph}>
123 You are running <code>react-devtools</code> version{' '}
124 <span className={styles.Version}>{DEVTOOLS_VERSION}</span>.
125 </p>
126 <p className={styles.Paragraph}>
127 This requires bridge protocol{' '}
128 <span className={styles.Version}>
129 version {currentBridgeProtocol.version}
130 </span>
131 . However the current backend version uses bridge protocol{' '}
132 <span className={styles.Version}>version {version}</span>.
133 </p>
134 {instructions}
135 <p className={styles.Paragraph}>
136 Or{' '}
137 <a className={styles.Link} href={INSTRUCTIONS_FB_URL} target="_blank">
138 click here
139 </a>{' '}
140 for more information.
141 </p>
142 </div>
143 </Fragment>
144 );
145 }