Skip to content

Commit

Permalink
[DevTools] Allow to continue dragging when leaving profiler picker (#…
Browse files Browse the repository at this point in the history
…18852)

Co-authored-by: Brian Vaughn <brian.david.vaughn@gmail.com>
  • Loading branch information
bl00mber and bvaughn authored May 8, 2020
1 parent df14b5b commit 6207743
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

import * as React from 'react';
import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {useEffect, useMemo, useRef, useState} from 'react';
import AutoSizer from 'react-virtualized-auto-sizer';
import {FixedSizeList} from 'react-window';
import SnapshotCommitListItem from './SnapshotCommitListItem';
Expand All @@ -20,11 +20,11 @@ export type ItemData = {|
commitDurations: Array<number>,
commitTimes: Array<number>,
filteredCommitIndices: Array<number>,
isMouseDown: boolean,
maxDuration: number,
selectedCommitIndex: number | null,
selectedFilteredCommitIndex: number | null,
selectCommitIndex: (index: number) => void,
startCommitDrag: (newDragState: DragState) => void,
|};

type Props = {|
Expand Down Expand Up @@ -73,6 +73,12 @@ type ListProps = {|
width: number,
|};

type DragState = {
commitIndex: number,
left: number,
sizeIncrement: number,
};

function List({
commitDurations,
selectedCommitIndex,
Expand All @@ -97,28 +103,6 @@ function List({
}
}, [listRef, selectedFilteredCommitIndex]);

// When the mouse is down, dragging over a commit should auto-select it.
// This provides a nice way for users to swipe across a range of commits to compare them.
const [isMouseDown, setIsMouseDown] = useState(false);
const handleMouseDown = useCallback(() => {
setIsMouseDown(true);
}, []);
const handleMouseUp = useCallback(() => {
setIsMouseDown(false);
}, []);
useEffect(() => {
if (divRef.current === null) {
return () => {};
}

// It's important to listen to the ownerDocument to support the browser extension.
// Here we use portals to render individual tabs (e.g. Profiler),
// and the root document might belong to a different window.
const ownerDocument = divRef.current.ownerDocument;
ownerDocument.addEventListener('mouseup', handleMouseUp);
return () => ownerDocument.removeEventListener('mouseup', handleMouseUp);
}, [divRef, handleMouseUp]);

const itemSize = useMemo(
() => Math.max(minBarWidth, width / filteredCommitIndices.length),
[filteredCommitIndices, width],
Expand All @@ -128,23 +112,76 @@ function List({
[commitDurations],
);

const maxCommitIndex = filteredCommitIndices.length - 1;

const [dragState, setDragState] = useState<DragState | null>(null);

const handleDragCommit = ({buttons, pageX}: any) => {
if (buttons === 0) {
setDragState(null);
return;
}

if (dragState !== null) {
const {commitIndex, left, sizeIncrement} = dragState;

let newCommitIndex = commitIndex;
let newCommitLeft = left;

if (pageX < newCommitLeft) {
while (pageX < newCommitLeft) {
newCommitLeft -= sizeIncrement;
newCommitIndex -= 1;
}
} else {
let newCommitRectRight = newCommitLeft + sizeIncrement;
while (pageX > newCommitRectRight) {
newCommitRectRight += sizeIncrement;
newCommitIndex += 1;
}
}

if (newCommitIndex < 0) {
newCommitIndex = 0;
} else if (newCommitIndex > maxCommitIndex) {
newCommitIndex = maxCommitIndex;
}

selectCommitIndex(newCommitIndex);
}
};

useEffect(() => {
if (dragState === null) {
return;
}

const element = divRef.current;
if (element !== null) {
const ownerDocument = element.ownerDocument;
ownerDocument.addEventListener('mousemove', handleDragCommit);
return () => {
ownerDocument.removeEventListener('mousemove', handleDragCommit);
};
}
}, [dragState]);

// Pass required contextual data down to the ListItem renderer.
const itemData = useMemo<ItemData>(
() => ({
commitDurations,
commitTimes,
filteredCommitIndices,
isMouseDown,
maxDuration,
selectedCommitIndex,
selectedFilteredCommitIndex,
selectCommitIndex,
startCommitDrag: setDragState,
}),
[
commitDurations,
commitTimes,
filteredCommitIndices,
isMouseDown,
maxDuration,
selectedCommitIndex,
selectedFilteredCommitIndex,
Expand All @@ -153,11 +190,7 @@ function List({
);

return (
<div
onMouseDown={handleMouseDown}
onMouseUp={handleMouseUp}
ref={divRef}
style={{height, width}}>
<div ref={divRef} style={{height, width}}>
<FixedSizeList
className={styles.List}
layout="horizontal"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

import * as React from 'react';
import {memo, useCallback} from 'react';
import {memo} from 'react';
import {areEqual} from 'react-window';
import {getGradientColor, formatDuration, formatTime} from './utils';

Expand All @@ -28,22 +28,17 @@ function SnapshotCommitListItem({data: itemData, index, style}: Props) {
commitDurations,
commitTimes,
filteredCommitIndices,
isMouseDown,
maxDuration,
selectedCommitIndex,
selectCommitIndex,
startCommitDrag,
} = itemData;

index = filteredCommitIndices[index];

const commitDuration = commitDurations[index];
const commitTime = commitTimes[index];

const handleClick = useCallback(() => selectCommitIndex(index), [
index,
selectCommitIndex,
]);

// Guard against commits with duration 0
const percentage =
Math.min(1, Math.max(0, commitDuration / maxDuration)) || 0;
Expand All @@ -52,11 +47,21 @@ function SnapshotCommitListItem({data: itemData, index, style}: Props) {
// Leave a 1px gap between snapshots
const width = parseFloat(style.width) - 1;

const handleMouseDown = ({buttons, target}: any) => {
if (buttons === 1) {
selectCommitIndex(index);
startCommitDrag({
commitIndex: index,
left: target.getBoundingClientRect().left,
sizeIncrement: parseFloat(style.width),
});
}
};

return (
<div
className={styles.Outer}
onClick={handleClick}
onMouseEnter={isMouseDown ? handleClick : null}
onMouseDown={handleMouseDown}
style={{
...style,
width,
Expand Down

0 comments on commit 6207743

Please sign in to comment.