Skip to content

Commit

Permalink
support launch editor feature for selected component
Browse files Browse the repository at this point in the history
  • Loading branch information
iChenLei committed Feb 16, 2021
1 parent 1a74726 commit 404b4af
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 0 deletions.
32 changes: 32 additions & 0 deletions packages/react-devtools-shared/src/backend/agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ type PersistedSelection = {|
path: Array<PathFrame>,
|};

type LaunchEditorParams = {|
launchEditorEndpoint: string,
fileName: string,
lineNumber: string,
|};

export default class Agent extends EventEmitter<{|
hideNativeHighlight: [],
showNativeHighlight: [NativeType],
Expand Down Expand Up @@ -201,6 +207,7 @@ export default class Agent extends EventEmitter<{|
bridge.addListener('updateComponentFilters', this.updateComponentFilters);
bridge.addListener('viewAttributeSource', this.viewAttributeSource);
bridge.addListener('viewElementSource', this.viewElementSource);
bridge.addListener('launchEditor', this.launchEditor);

// Temporarily support older standalone front-ends sending commands to newer embedded backends.
// We do this because React Native embeds the React DevTools backend,
Expand Down Expand Up @@ -655,6 +662,31 @@ export default class Agent extends EventEmitter<{|
}
};

launchEditor = ({
launchEditorEndpoint,
fileName,
lineNumber,
}: LaunchEditorParams) => {
fetch(
`/${launchEditorEndpoint}?fileName=${fileName}&lineNumber=${lineNumber}`,
)
.then(res => {
if (res.ok) {
console.log(`open ${fileName} in editor success`);
} else {
console.warn(`open ${fileName} in editor failed`);
console.warn(
'Please make sure the open editor server middleware(e.g. react-dev-utils) is installed correctly!',
);
}
})
.catch(_ => {
console.error(
'make sure the open editor server middleware(e.g. react-dev-utils) installed correctly!',
);
});
};

viewElementSource = ({id, rendererID}: ElementAndRendererID) => {
const renderer = this._rendererInterfaces[rendererID];
if (renderer == null) {
Expand Down
7 changes: 7 additions & 0 deletions packages/react-devtools-shared/src/bridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ type UpdateConsolePatchSettingsParams = {|
showInlineWarningsAndErrors: boolean,
|};

type LauchEditorParams = {|
launchEditorEndpoint: string,
fileName: string,
lineNumber: string,
|};

export type BackendEvents = {|
extensionBackendInitialized: [],
inspectedElement: [InspectedElementPayload],
Expand Down Expand Up @@ -173,6 +179,7 @@ type FrontendEvents = {|
updateConsolePatchSettings: [UpdateConsolePatchSettingsParams],
viewAttributeSource: [ViewAttributeSourceParams],
viewElementSource: [ElementAndRendererID],
launchEditor: [LauchEditorParams],

// React Native style editor plug-in.
NativeStyleEditor_measure: [ElementAndRendererID],
Expand Down
10 changes: 10 additions & 0 deletions packages/react-devtools-shared/src/devtools/views/ButtonIcon.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export type IconType =
| 'export'
| 'filter'
| 'import'
| 'launch-editor'
| 'log-data'
| 'more'
| 'next'
Expand Down Expand Up @@ -124,6 +125,9 @@ export default function ButtonIcon({className = '', type}: Props) {
case 'view-source':
pathData = PATH_VIEW_SOURCE;
break;
case 'launch-editor':
pathData = PATH_LAUNCH_EDITOR;
break;
default:
console.warn(`Unsupported type "${type}" specified for ButtonIcon`);
break;
Expand Down Expand Up @@ -244,3 +248,9 @@ const PATH_VIEW_DOM = `
const PATH_VIEW_SOURCE = `
M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z
`;

const PATH_LAUNCH_EDITOR = `M896 435.2a25.6 25.6 0 0 1-25.6-25.6v-256H640a25.6 25.6 0 1 1 0-51.2h256a25.6 25.6 0 0 1 25.6
25.6v281.6a25.6 25.6 0 0 1-25.6 25.6zM844.8 921.6H128a25.6 25.6 0 0 1-25.6-25.6V179.2a25.6 25.6 0 0 1 25.6-25.6h358.4a25.6
25.6 0 1 1 0 51.2H153.6v665.6h665.6V537.6a25.6 25.6 0 1 1 51.2 0V896a25.6 25.6 0 0 1-25.6 25.6zM533.952 515.648a25.6
25.6 0 0 1-18.112-43.712l362.048-362.048a25.6 25.6 0 0 1 36.224 36.224L552.064 508.16a25.472 25.472 0 0 1-18.112 7.488z
`;
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import * as React from 'react';
import {Fragment, useCallback, useContext} from 'react';
import {TreeDispatcherContext} from './TreeContext';
import {BridgeContext, ContextMenuContext, StoreContext} from '../context';
import {SettingsContext} from '../Settings/SettingsContext';
import ContextMenu from '../../ContextMenu/ContextMenu';
import ContextMenuItem from '../../ContextMenu/ContextMenuItem';
import Button from '../Button';
Expand Down Expand Up @@ -241,11 +242,26 @@ type SourceProps = {|
|};

function Source({fileName, lineNumber}: SourceProps) {
const bridge = useContext(BridgeContext);
const {launchEditorEndpoint} = useContext(SettingsContext);

const handleCopy = () => copy(`${fileName}:${lineNumber}`);
const handleLaunchEditor = () => {
bridge.send('launchEditor', {
launchEditorEndpoint,
fileName,
lineNumber,
});
};
return (
<div className={styles.Source}>
<div className={styles.SourceHeaderRow}>
<div className={styles.SourceHeader}>source</div>
<Button
onClick={handleLaunchEditor}
title="open react component source file in your editor">
<ButtonIcon type="search" />
</Button>
<Button onClick={handleCopy} title="Copy to clipboard">
<ButtonIcon type="copy" />
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ import styles from './SettingsShared.css';
export default function GeneralSettings(_: {||}) {
const {
displayDensity,
launchEditorEndpoint,
setDisplayDensity,
setTheme,
setLaunchEditorEndpoint,
setTraceUpdatesEnabled,
theme,
traceUpdatesEnabled,
Expand Down Expand Up @@ -54,6 +56,18 @@ export default function GeneralSettings(_: {||}) {
</select>
</div>

<div className={styles.Setting}>
<div className={styles.RadioLabel}>Launch Editor Endpoint</div>
<input
className={styles.Input}
onChange={({currentTarget}) =>
setLaunchEditorEndpoint(currentTarget.value)
}
type="txt"
placeholder={launchEditorEndpoint}
/>
</div>

{supportsTraceUpdates && (
<div className={styles.Setting}>
<label>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ type Context = {|
theme: Theme,
setTheme(value: Theme): void,

launchEditorEndpoint: string,
setLaunchEditorEndpoint(value: string): void,

traceUpdatesEnabled: boolean,
setTraceUpdatesEnabled: (value: boolean) => void,
|};
Expand Down Expand Up @@ -83,6 +86,14 @@ function SettingsContextController({
'React::DevTools::theme',
'auto',
);
const [
launchEditorEndpoint,
setLaunchEditorEndpoint,
] = useLocalStorage<string>(
'React::DevTools::launchEditorEndpoint',
'__open-stack-frame-in-editor',
);

const [
appendComponentStack,
setAppendComponentStack,
Expand Down Expand Up @@ -176,13 +187,15 @@ function SettingsContextController({
appendComponentStack,
breakOnConsoleErrors,
displayDensity,
launchEditorEndpoint,
lineHeight:
displayDensity === 'compact'
? COMPACT_LINE_HEIGHT
: COMFORTABLE_LINE_HEIGHT,
setAppendComponentStack,
setBreakOnConsoleErrors,
setDisplayDensity,
setLaunchEditorEndpoint,
setTheme,
setTraceUpdatesEnabled,
setShowInlineWarningsAndErrors,
Expand All @@ -194,9 +207,11 @@ function SettingsContextController({
appendComponentStack,
breakOnConsoleErrors,
displayDensity,
launchEditorEndpoint,
setAppendComponentStack,
setBreakOnConsoleErrors,
setDisplayDensity,
setLaunchEditorEndpoint,
setTheme,
setTraceUpdatesEnabled,
setShowInlineWarningsAndErrors,
Expand Down

0 comments on commit 404b4af

Please sign in to comment.