88 */
99
1010import * as React from 'react' ;
11- import { useCallback , useEffect , useMemo , useRef , useState } from 'react' ;
11+ import { useEffect , useMemo , useRef , useState } from 'react' ;
1212import AutoSizer from 'react-virtualized-auto-sizer' ;
1313import { FixedSizeList } from 'react-window' ;
1414import SnapshotCommitListItem from './SnapshotCommitListItem' ;
@@ -20,11 +20,11 @@ export type ItemData = {|
2020 commitDurations : Array < number > ,
2121 commitTimes : Array < number > ,
2222 filteredCommitIndices : Array < number > ,
23- isMouseDown : boolean ,
2423 maxDuration : number ,
2524 selectedCommitIndex : number | null ,
2625 selectedFilteredCommitIndex : number | null ,
2726 selectCommitIndex : ( index : number ) => void ,
27+ startCommitDrag : ( newDragState : DragState ) => void ,
2828| } ;
2929
3030type Props = { |
@@ -73,6 +73,12 @@ type ListProps = {|
7373 width : number ,
7474| } ;
7575
76+ type DragState = {
77+ commitIndex : number ,
78+ left : number ,
79+ sizeIncrement : number ,
80+ } ;
81+
7682function List ( {
7783 commitDurations,
7884 selectedCommitIndex,
@@ -97,28 +103,6 @@ function List({
97103 }
98104 } , [ listRef , selectedFilteredCommitIndex ] ) ;
99105
100- // When the mouse is down, dragging over a commit should auto-select it.
101- // This provides a nice way for users to swipe across a range of commits to compare them.
102- const [ isMouseDown , setIsMouseDown ] = useState ( false ) ;
103- const handleMouseDown = useCallback ( ( ) => {
104- setIsMouseDown ( true ) ;
105- } , [ ] ) ;
106- const handleMouseUp = useCallback ( ( ) => {
107- setIsMouseDown ( false ) ;
108- } , [ ] ) ;
109- useEffect ( ( ) => {
110- if ( divRef . current === null ) {
111- return ( ) => { } ;
112- }
113-
114- // It's important to listen to the ownerDocument to support the browser extension.
115- // Here we use portals to render individual tabs (e.g. Profiler),
116- // and the root document might belong to a different window.
117- const ownerDocument = divRef . current . ownerDocument ;
118- ownerDocument . addEventListener ( 'mouseup' , handleMouseUp ) ;
119- return ( ) => ownerDocument . removeEventListener ( 'mouseup' , handleMouseUp ) ;
120- } , [ divRef , handleMouseUp ] ) ;
121-
122106 const itemSize = useMemo (
123107 ( ) => Math . max ( minBarWidth , width / filteredCommitIndices . length ) ,
124108 [ filteredCommitIndices , width ] ,
@@ -128,23 +112,76 @@ function List({
128112 [ commitDurations ] ,
129113 ) ;
130114
115+ const maxCommitIndex = filteredCommitIndices . length - 1 ;
116+
117+ const [ dragState , setDragState ] = useState < DragState | null > ( null ) ;
118+
119+ const handleDragCommit = ( { buttons, pageX} : any ) => {
120+ if ( buttons === 0 ) {
121+ setDragState ( null ) ;
122+ return ;
123+ }
124+
125+ if ( dragState !== null ) {
126+ const { commitIndex, left, sizeIncrement} = dragState ;
127+
128+ let newCommitIndex = commitIndex ;
129+ let newCommitLeft = left ;
130+
131+ if ( pageX < newCommitLeft ) {
132+ while ( pageX < newCommitLeft ) {
133+ newCommitLeft -= sizeIncrement ;
134+ newCommitIndex -= 1 ;
135+ }
136+ } else {
137+ let newCommitRectRight = newCommitLeft + sizeIncrement ;
138+ while ( pageX > newCommitRectRight ) {
139+ newCommitRectRight += sizeIncrement ;
140+ newCommitIndex += 1 ;
141+ }
142+ }
143+
144+ if ( newCommitIndex < 0 ) {
145+ newCommitIndex = 0 ;
146+ } else if ( newCommitIndex > maxCommitIndex ) {
147+ newCommitIndex = maxCommitIndex ;
148+ }
149+
150+ selectCommitIndex ( newCommitIndex ) ;
151+ }
152+ } ;
153+
154+ useEffect ( ( ) => {
155+ if ( dragState === null ) {
156+ return ;
157+ }
158+
159+ const element = divRef . current ;
160+ if ( element !== null ) {
161+ const ownerDocument = element . ownerDocument ;
162+ ownerDocument . addEventListener ( 'mousemove' , handleDragCommit ) ;
163+ return ( ) => {
164+ ownerDocument . removeEventListener ( 'mousemove' , handleDragCommit ) ;
165+ } ;
166+ }
167+ } , [ dragState ] ) ;
168+
131169 // Pass required contextual data down to the ListItem renderer.
132170 const itemData = useMemo < ItemData > (
133171 ( ) => ( {
134172 commitDurations,
135173 commitTimes,
136174 filteredCommitIndices,
137- isMouseDown,
138175 maxDuration,
139176 selectedCommitIndex,
140177 selectedFilteredCommitIndex,
141178 selectCommitIndex,
179+ startCommitDrag : setDragState ,
142180 } ) ,
143181 [
144182 commitDurations ,
145183 commitTimes ,
146184 filteredCommitIndices ,
147- isMouseDown ,
148185 maxDuration ,
149186 selectedCommitIndex ,
150187 selectedFilteredCommitIndex ,
@@ -153,11 +190,7 @@ function List({
153190 ) ;
154191
155192 return (
156- < div
157- onMouseDown = { handleMouseDown }
158- onMouseUp = { handleMouseUp }
159- ref = { divRef }
160- style = { { height, width} } >
193+ < div ref = { divRef } style = { { height, width} } >
161194 < FixedSizeList
162195 className = { styles . List }
163196 layout = "horizontal"
0 commit comments