Skip to content

Commit 9e916c2

Browse files
committed
[DevTools] hotkey to start/stop profiling
1 parent 5268492 commit 9e916c2

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

packages/react-devtools-shared/src/devtools/views/Profiler/Profiler.js

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*/
99

1010
import * as React from 'react';
11-
import {Fragment, useContext} from 'react';
11+
import {Fragment, useContext, useEffect, useRef} from 'react';
1212
import {ModalDialog} from '../ModalDialog';
1313
import {ProfilerContext} from './ProfilerContext';
1414
import TabBar from '../TabBar';
@@ -38,6 +38,8 @@ import {TimelineContext} from 'react-devtools-timeline/src/TimelineContext';
3838
import styles from './Profiler.css';
3939

4040
function Profiler(_: {}) {
41+
const profilerRef = useRef<HTMLDivElement | null>(null);
42+
4143
const {
4244
didRecordCommits,
4345
isProcessingData,
@@ -47,6 +49,8 @@ function Profiler(_: {}) {
4749
selectedTabID,
4850
selectTab,
4951
supportsProfiling,
52+
startProfiling,
53+
stopProfiling,
5054
} = useContext(ProfilerContext);
5155

5256
const {file: timelineTraceEventData, searchInputContainerRef} =
@@ -56,6 +60,34 @@ function Profiler(_: {}) {
5660

5761
const isLegacyProfilerSelected = selectedTabID !== 'timeline';
5862

63+
// Cmd+E to start/stop profiler recording
64+
useEffect(() => {
65+
const div = profilerRef.current;
66+
if (div === null) {
67+
return;
68+
}
69+
70+
const ownerWindow = div.ownerDocument.defaultView;
71+
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
72+
const handleKeyDown = (event: KeyboardEvent) => {
73+
const correctModifier = isMac ? event.metaKey : event.ctrlKey;
74+
if (correctModifier && event.key === 'e') {
75+
if (isProfiling) {
76+
stopProfiling();
77+
} else {
78+
startProfiling();
79+
}
80+
event.preventDefault();
81+
event.stopPropagation();
82+
}
83+
};
84+
85+
ownerWindow.addEventListener('keydown', handleKeyDown);
86+
return () => {
87+
ownerWindow.removeEventListener('keydown', handleKeyDown);
88+
};
89+
}, [isProfiling, startProfiling, stopProfiling]);
90+
5991
let view = null;
6092
if (didRecordCommits || selectedTabID === 'timeline') {
6193
switch (selectedTabID) {
@@ -112,7 +144,7 @@ function Profiler(_: {}) {
112144

113145
return (
114146
<SettingsModalContextController>
115-
<div className={styles.Profiler}>
147+
<div ref={profilerRef} className={styles.Profiler}>
116148
<div className={styles.LeftColumn}>
117149
<div className={styles.Toolbar}>
118150
<RecordToggle disabled={!supportsProfiling} />

packages/react-devtools-shared/src/devtools/views/Profiler/RecordToggle.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,17 @@ export default function RecordToggle({disabled}: Props): React.Node {
3030
className = styles.ActiveRecordToggle;
3131
}
3232

33+
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
34+
const shortcut = isMac ? '⌘E' : 'Ctrl+E';
35+
const title = isProfiling ? `Stop profiling - ${shortcut}` : `Start profiling - ${shortcut}`;
36+
3337
return (
3438
<Button
3539
className={className}
3640
disabled={disabled}
3741
onClick={isProfiling ? stopProfiling : startProfiling}
3842
testName="ProfilerToggleButton"
39-
title={isProfiling ? 'Stop profiling' : 'Start profiling'}>
43+
title={title}>
4044
<ButtonIcon type="record" />
4145
</Button>
4246
);

0 commit comments

Comments
 (0)