Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.

Commit b7500e8

Browse files
author
Brian Vaughn
committed
Incorporated some interactions feedback from Shirley Wu:
1. Replace interaction commit circles with squares 2. Color commits in both the main and right-side pane based on their duration (to tie into other chart views) 3. Remove click-to-select commit because this surprised Sophie and Shirley initially
1 parent 01a8ffb commit b7500e8

File tree

4 files changed

+68
-101
lines changed

4 files changed

+68
-101
lines changed

plugins/Profiler/views/InteractionTimeline.js

Lines changed: 35 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,13 @@ import React, { PureComponent } from 'react';
1818
import { FixedSizeList as List } from 'react-window';
1919
import AutoSizer from 'react-virtualized-auto-sizer';
2020
import NoInteractionsMessage from './NoInteractionsMessage';
21-
import { scale } from './constants';
21+
import { getGradientColor, scale } from './constants';
2222

2323
const INTERACTION_SIZE = 4;
2424
const ITEM_SIZE = 25;
2525
const SNAPSHOT_SIZE = 10;
2626

2727
type SelectInteraction = (interaction: Interaction) => void;
28-
type ViewSnapshot = (snapshot: Snapshot) => void;
2928

3029
type ChartItem = {|
3130
interaction: Interaction,
@@ -35,6 +34,7 @@ type ChartItem = {|
3534

3635
type ChartData = {|
3736
items: Array<ChartItem>,
37+
maxDuration: number,
3838
stopTime: number,
3939
|};
4040

@@ -47,38 +47,37 @@ type ItemData = {|
4747
selectedSnapshot: Snapshot,
4848
selectInteraction: SelectInteraction,
4949
theme: Theme,
50-
viewSnapshot: ViewSnapshot,
5150
|};
5251

5352
type Props = {|
5453
cacheInteractionData: CacheInteractionData,
5554
getCachedInteractionData: GetCachedInteractionData,
5655
hasMultipleRoots: boolean,
5756
interactionsToSnapshots: Map<Interaction, Set<Snapshot>>,
57+
maxDuration: number,
5858
selectedInteraction: Interaction | null,
5959
selectedSnapshot: Snapshot,
6060
selectInteraction: SelectInteraction,
6161
theme: Theme,
6262
timestampsToInteractions: Map<number, Set<Interaction>>,
63-
viewSnapshot: ViewSnapshot,
6463
|};
6564

6665
const InteractionTimeline = ({
6766
cacheInteractionData,
6867
getCachedInteractionData,
6968
hasMultipleRoots,
7069
interactionsToSnapshots,
70+
maxDuration,
7171
selectedInteraction,
7272
selectedSnapshot,
7373
selectInteraction,
7474
theme,
7575
timestampsToInteractions,
76-
viewSnapshot,
7776
}: Props) => {
7877
// Cache data in ProfilerStore so we only have to compute it the first time the interactions tab is shown
7978
let chartData = getCachedInteractionData(selectedSnapshot.root);
8079
if (chartData === null) {
81-
chartData = getChartData(interactionsToSnapshots, timestampsToInteractions);
80+
chartData = getChartData(interactionsToSnapshots, maxDuration, timestampsToInteractions);
8281
cacheInteractionData(selectedSnapshot.root, chartData);
8382
}
8483

@@ -94,7 +93,6 @@ const InteractionTimeline = ({
9493
selectInteraction={selectInteraction}
9594
theme={theme}
9695
width={width}
97-
viewSnapshot={viewSnapshot}
9896
/>
9997
)}
10098
</AutoSizer>
@@ -109,7 +107,6 @@ type InteractionsListProps = {|
109107
selectedSnapshot: Snapshot,
110108
selectInteraction: SelectInteraction,
111109
theme: Theme,
112-
viewSnapshot: ViewSnapshot,
113110
width: number,
114111
|};
115112

@@ -153,7 +150,6 @@ class InteractionsList extends PureComponent<InteractionsListProps, void> {
153150
selectedSnapshot,
154151
selectInteraction,
155152
theme,
156-
viewSnapshot,
157153
width,
158154
} = this.props;
159155

@@ -176,7 +172,6 @@ class InteractionsList extends PureComponent<InteractionsListProps, void> {
176172
selectedSnapshot,
177173
selectInteraction,
178174
theme,
179-
viewSnapshot,
180175
width,
181176
);
182177

@@ -214,44 +209,36 @@ type ListItemProps = {|
214209
|};
215210
type ListItemState = {|
216211
isHovered: boolean,
217-
hoveredSnapshot: Snapshot | null,
218212
|};
219213

220214
class ListItem extends PureComponent<ListItemProps, ListItemState> {
221215
state = {
222216
isHovered: false,
223-
hoveredSnapshot: null,
224217
};
225218

226-
handleMouseEnter = (snapshot: Snapshot | null) => this.setState({
227-
isHovered: true,
228-
hoveredSnapshot: snapshot,
229-
});
230-
219+
handleMouseEnter = () => this.setState({isHovered: true});
231220
handleMouseLeave = () => this.setState({isHovered: false});
232221

233222
render() {
234223
const { data: itemData, index: itemIndex, style } = this.props;
235-
const { isHovered, hoveredSnapshot } = this.state;
224+
const { isHovered } = this.state;
236225

237226
const { chartData, labelColumnWidth, scaleX, selectedInteraction, selectedSnapshot, theme } = itemData;
238-
const { items } = chartData;
227+
const { items, maxDuration } = chartData;
239228

240229
const item: ChartItem = items[itemIndex];
241230
const { interaction, lastSnapshotCommitTime } = item;
242231

243-
const showRowHover = isHovered && hoveredSnapshot === null;
244-
245232
return (
246233
<div
247234
onClick={() => itemData.selectInteraction(interaction)}
248-
onMouseEnter={() => this.handleMouseEnter(null)}
235+
onMouseEnter={this.handleMouseEnter}
249236
onMouseLeave={this.handleMouseLeave}
250237
style={{
251238
...style,
252239
display: 'flex',
253240
alignItems: 'center',
254-
backgroundColor: showRowHover ? theme.state03 : (selectedInteraction === interaction ? theme.base01 : 'transparent'),
241+
backgroundColor: isHovered ? theme.state03 : (selectedInteraction === interaction ? theme.base01 : 'transparent'),
255242
borderBottom: `1px solid ${theme.base01}`,
256243
cursor: 'pointer',
257244
}}
@@ -265,8 +252,8 @@ class ListItem extends PureComponent<ListItemProps, ListItemState> {
265252
lineHeight: `${ITEM_SIZE}px`,
266253
boxSizing: 'border-box',
267254
padding: '0 0.25rem',
268-
color: showRowHover ? theme.state00 : theme.base05,
269-
textDecoration: showRowHover ? 'underline' : 'none',
255+
color: isHovered ? theme.state00 : theme.base05,
256+
textDecoration: isHovered ? 'underline' : 'none',
270257
userSelect: 'none',
271258
}}
272259
title={interaction.name}
@@ -283,32 +270,35 @@ class ListItem extends PureComponent<ListItemProps, ListItemState> {
283270
borderRadius: '0.125rem',
284271
}}
285272
/>
286-
{item.snapshots.map((snapshot, snapshotIndex) => (
287-
<div
288-
key={snapshotIndex}
289-
onClick={() => itemData.viewSnapshot(snapshot)}
290-
onMouseEnter={() => this.handleMouseEnter(snapshot)}
291-
onMouseLeave={() => this.handleMouseEnter(null)}
292-
style={{
293-
position: 'absolute',
294-
left: `${labelColumnWidth + scaleX(snapshot.commitTime)}px`,
295-
width: `${SNAPSHOT_SIZE}px`,
296-
height: `${SNAPSHOT_SIZE}px`,
297-
borderRadius: `${SNAPSHOT_SIZE}px`,
298-
backgroundColor: hoveredSnapshot === snapshot || selectedSnapshot === snapshot ? theme.state00 : theme.base00,
299-
border: `2px solid ${theme.state00}`,
300-
boxSizing: 'border-box',
301-
cursor: 'pointer',
302-
}}
303-
/>
304-
))}
273+
{item.snapshots.map((snapshot, snapshotIndex) => {
274+
// Guard against commits with duration 0
275+
const percentage = Math.min(1, Math.max(0, snapshot.duration / maxDuration)) || 0;
276+
277+
return (
278+
<div
279+
key={snapshotIndex}
280+
style={{
281+
position: 'absolute',
282+
left: `${labelColumnWidth + scaleX(snapshot.commitTime)}px`,
283+
width: `${SNAPSHOT_SIZE}px`,
284+
height: `${SNAPSHOT_SIZE}px`,
285+
backgroundColor: selectedSnapshot === snapshot
286+
? theme.state06
287+
: getGradientColor(percentage),
288+
boxSizing: 'border-box',
289+
cursor: 'pointer',
290+
}}
291+
/>
292+
);
293+
})}
305294
</div>
306295
);
307296
}
308297
}
309298

310299
const getChartData = memoize((
311300
interactionsToSnapshots: Map<Interaction, Set<Snapshot>>,
301+
maxDuration: number,
312302
timestampsToInteractions: Map<number, Set<Interaction>>,
313303
): ChartData => {
314304
const items: Array<ChartItem> = [];
@@ -332,6 +322,7 @@ const getChartData = memoize((
332322

333323
return {
334324
items,
325+
maxDuration,
335326
stopTime,
336327
};
337328
});
@@ -342,7 +333,6 @@ const getItemData = memoize((
342333
selectedSnapshot: Snapshot,
343334
selectInteraction: SelectInteraction,
344335
theme: Theme,
345-
viewSnapshot: ViewSnapshot,
346336
width: number,
347337
): ItemData => {
348338
const labelColumnWidth = Math.min(200, width / 5);
@@ -357,7 +347,6 @@ const getItemData = memoize((
357347
selectedSnapshot,
358348
selectInteraction,
359349
theme,
360-
viewSnapshot,
361350
};
362351
});
363352

plugins/Profiler/views/ProfilerInteractionDetailPane.js

Lines changed: 25 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@ import type {Theme} from '../../../frontend/types';
1414
import type {Interaction, Snapshot} from '../ProfilerTypes';
1515

1616
import React, {Fragment} from 'react';
17-
import { formatDuration, formatPercentage, formatTime } from './constants';
17+
import { getGradientColor, formatDuration, formatTime } from './constants';
1818
import {sansSerif} from '../../../frontend/Themes/Fonts';
1919
import Hoverable from '../../../frontend/Hoverable';
2020

2121
type ViewSnapshot = (snapshot: Snapshot) => void;
2222

2323
type Props = {|
2424
interaction: Interaction,
25+
maxDuration: number,
2526
selectedSnapshot: Snapshot | null,
2627
snapshots: Set<Snapshot>,
2728
theme: Theme,
@@ -30,6 +31,7 @@ type Props = {|
3031

3132
const ProfilerInteractionDetailPane = ({
3233
interaction,
34+
maxDuration,
3335
selectedSnapshot,
3436
snapshots,
3537
theme,
@@ -50,16 +52,19 @@ const ProfilerInteractionDetailPane = ({
5052
overflow: 'hidden',
5153
textOverflow: 'ellipsis',
5254
whiteSpace: 'nowrap',
55+
display: 'flex',
56+
justifyContent: 'space-between',
5357
}}
5458
title={interaction.name}
5559
>
56-
{interaction.name}
60+
{interaction.name} at {formatTime(interaction.timestamp)}s
5761
</div>
5862
<div style={{
5963
padding: '0.5rem',
6064
}}>
61-
<div><strong>Timestamp</strong>: {formatTime(interaction.timestamp)}s</div>
62-
<div style={{margin: '0.5rem 0'}}><strong>Renders</strong>:</div>
65+
<div style={{marginBottom: '0.5rem'}}>
66+
<strong>Commits</strong>:
67+
</div>
6368
<ul style={{
6469
listStyle: 'none',
6570
margin: 0,
@@ -72,6 +77,7 @@ const ProfilerInteractionDetailPane = ({
7277
return (
7378
<SnapshotLink
7479
key={index}
80+
maxDuration={maxDuration}
7581
onClick={() => viewSnapshot(snapshot)}
7682
previousTimestamp={previousTimestamp}
7783
selectedSnapshot={selectedSnapshot}
@@ -89,6 +95,7 @@ const ProfilerInteractionDetailPane = ({
8995

9096
const SnapshotLink = Hoverable(({
9197
isHovered,
98+
maxDuration,
9299
onClick,
93100
onMouseEnter,
94101
onMouseLeave,
@@ -98,9 +105,6 @@ const SnapshotLink = Hoverable(({
98105
theme,
99106
viewSnapshot,
100107
}) => {
101-
const cpuPercentage = Math.max(0, Math.min(snapshot.duration / (snapshot.commitTime - previousTimestamp)));
102-
const cpuSvg = CPU_SVGS[Math.round(cpuPercentage * (CPU_SVGS.length - 1))];
103-
104108
return (
105109
<li
106110
onClick={onClick}
@@ -114,59 +118,26 @@ const SnapshotLink = Hoverable(({
114118
display: 'flex',
115119
alignItems: 'center',
116120
padding: '0.5rem',
117-
borderBottom: `1px solid ${theme.base01}`,
121+
borderTop: `1px solid ${theme.base01}`,
118122
}}
119123
>
120-
{cpuSvg}
124+
<div
125+
style={{
126+
width: '1rem',
127+
height: '1rem',
128+
backgroundColor: getGradientColor(snapshot.duration / maxDuration),
129+
}}
130+
/>
121131
<ul style={{paddingLeft: '1.5rem'}}>
122-
<li>Timestamp: {formatTime(snapshot.commitTime)}s</li>
123-
<li>Duration: {formatDuration(snapshot.duration)}ms</li>
124-
<li>CPU: {formatPercentage(cpuPercentage)}%</li>
132+
<li style={{marginBottom: '0.25rem'}}>
133+
Timestamp: {formatTime(snapshot.commitTime)}s
134+
</li>
135+
<li>
136+
Duration: {formatDuration(snapshot.duration)}ms
137+
</li>
125138
</ul>
126139
</li>
127140
);
128141
});
129142

130-
const CPU_STYLE = {
131-
width: '1.5rem',
132-
height: '1.5rem',
133-
fill: 'currentColor',
134-
marginRight: '0.5rem',
135-
};
136-
137-
const CPU_0 = (
138-
<svg style={CPU_STYLE} viewBox="0 0 24 24">
139-
<path fillOpacity=".3" d="M2 22h20V2z" />
140-
</svg>
141-
);
142-
143-
const CPU_25 = (
144-
<svg style={CPU_STYLE} viewBox="0 0 24 24">
145-
<path fillOpacity=".3" d="M2 22h20V2z" />
146-
<path d="M12 12L2 22h10z" />
147-
</svg>
148-
);
149-
150-
const CPU_50 = (
151-
<svg style={CPU_STYLE} viewBox="0 0 24 24">
152-
<path fillOpacity=".3" d="M2 22h20V2z" />
153-
<path d="M14 10L2 22h12z" />
154-
</svg>
155-
);
156-
157-
const CPU_75 = (
158-
<svg style={CPU_STYLE} viewBox="0 0 24 24">
159-
<path fillOpacity=".3" d="M2 22h20V2z" />
160-
<path d="M17 7L2 22h15z" />
161-
</svg>
162-
);
163-
164-
const CPU_100 = (
165-
<svg style={CPU_STYLE} viewBox="0 0 24 24">
166-
<path d="M2 22h20V2z" />
167-
</svg>
168-
);
169-
170-
const CPU_SVGS = [CPU_0, CPU_25, CPU_50, CPU_75, CPU_100];
171-
172143
export default ProfilerInteractionDetailPane;

0 commit comments

Comments
 (0)