88 */
99
1010import * as React from 'react' ;
11- import { useEffect , useMemo , useRef } 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' ;
@@ -72,6 +72,12 @@ type ListProps = {|
7272 width : number ,
7373| } ;
7474
75+ type DragStartCommit = {
76+ dragStartCommitIndex : number ,
77+ rectLeft : number ,
78+ width : number ,
79+ } ;
80+
7581function List ( {
7682 commitDurations,
7783 selectedCommitIndex,
@@ -105,6 +111,87 @@ function List({
105111 [ commitDurations ] ,
106112 ) ;
107113
114+ const maxCommitIndex = filteredCommitIndices . length - 1 ;
115+
116+ const [ state , setState ] = useState ( {
117+ dragCommitStarted : false ,
118+ dragStartCommit : null ,
119+ modifiedIframes : null ,
120+ } ) ;
121+
122+ const startCommitDrag = ( newDragStartCommit : DragStartCommit ) => {
123+ const element = divRef . current ;
124+ if ( element !== null ) {
125+ const iframes = element . ownerDocument . querySelectorAll ( 'iframe' ) ;
126+ if ( iframes . length > 0 ) {
127+ const modifiedIframesMap = new Map ( ) ;
128+ for ( let i = 0 ; i < iframes . length ; i ++ ) {
129+ if ( iframes [ i ] . style . pointerEvents !== 'none' ) {
130+ modifiedIframesMap . set ( iframes [ i ] , iframes [ i ] . style . pointerEvents ) ;
131+ iframes [ i ] . style . pointerEvents = 'none' ;
132+ }
133+ }
134+ setState ( {
135+ dragCommitStarted : true ,
136+ dragStartCommit : newDragStartCommit ,
137+ modifiedIframes : modifiedIframesMap ,
138+ } ) ;
139+ }
140+ }
141+ } ;
142+
143+ const handleDragCommit = ( e : any ) => {
144+ const { dragCommitStarted, dragStartCommit, modifiedIframes} = state ;
145+ if ( dragCommitStarted === false || dragStartCommit === null ) return ;
146+ if ( e . buttons === 0 ) {
147+ if ( modifiedIframes !== null ) {
148+ modifiedIframes . forEach ( ( value , iframe ) => {
149+ iframe . style . pointerEvents = value ;
150+ } ) ;
151+ }
152+ setState ( {
153+ dragCommitStarted : false ,
154+ dragStartCommit : null ,
155+ modifiedIframes : null ,
156+ } ) ;
157+ return ;
158+ }
159+
160+ let newCommitIndex = dragStartCommit . dragStartCommitIndex ;
161+ let newCommitRectLeft = dragStartCommit . rectLeft ;
162+
163+ if ( e . pageX < dragStartCommit . rectLeft ) {
164+ while ( e . pageX < newCommitRectLeft ) {
165+ newCommitRectLeft = newCommitRectLeft - 1 - dragStartCommit . width ;
166+ newCommitIndex -= 1 ;
167+ }
168+ } else {
169+ let newCommitRectRight = newCommitRectLeft + dragStartCommit . width ;
170+ while ( e . pageX > newCommitRectRight ) {
171+ newCommitRectRight = newCommitRectRight + 1 + dragStartCommit . width ;
172+ newCommitIndex += 1 ;
173+ }
174+ }
175+
176+ if ( newCommitIndex < 0 ) {
177+ newCommitIndex = 0 ;
178+ } else if ( newCommitIndex > maxCommitIndex ) {
179+ newCommitIndex = maxCommitIndex ;
180+ }
181+ selectCommitIndex ( newCommitIndex ) ;
182+ } ;
183+
184+ useEffect ( ( ) => {
185+ const element = divRef . current ;
186+ if ( element !== null ) {
187+ const ownerDocument = element . ownerDocument ;
188+ ownerDocument . addEventListener ( 'mousemove' , handleDragCommit ) ;
189+ return ( ) => {
190+ ownerDocument . removeEventListener ( 'mousemove' , handleDragCommit ) ;
191+ } ;
192+ }
193+ } , [ state ] ) ;
194+
108195 // Pass required contextual data down to the ListItem renderer.
109196 const itemData = useMemo < ItemData > (
110197 ( ) => ( {
@@ -115,6 +202,7 @@ function List({
115202 selectedCommitIndex,
116203 selectedFilteredCommitIndex,
117204 selectCommitIndex,
205+ startCommitDrag,
118206 } ) ,
119207 [
120208 commitDurations ,
@@ -124,6 +212,7 @@ function List({
124212 selectedCommitIndex ,
125213 selectedFilteredCommitIndex ,
126214 selectCommitIndex ,
215+ startCommitDrag ,
127216 ] ,
128217 ) ;
129218
0 commit comments