@@ -74,6 +74,7 @@ interface CollectionPageState {
7474 directoryOutput : Result < DirectoryOutput > ;
7575 networkShareBaseUrl : Result < ConfigValue > ;
7676 selectedFileHashes : string [ ] ;
77+ lastSelectedFileHash ?: string ;
7778}
7879
7980export default class CollectionPage extends React . Component <
@@ -340,13 +341,43 @@ export default class CollectionPage extends React.Component<
340341 const coll = collOutput . CollectionWithMeta . Collection ; // shorthand
341342
342343 const fileCheckedChange = ( e : React . ChangeEvent < HTMLInputElement > ) => {
344+ const shiftPressed = e . nativeEvent instanceof MouseEvent && e . nativeEvent . shiftKey ;
345+ const selectMultiple = shiftPressed ;
346+
343347 // remove from currently selected, so depending on checked we can add or not add it
344348 const selectedFileHashes = this . state . selectedFileHashes . filter (
345349 ( sel ) => sel !== e . target . value ,
346350 ) ;
347351
348352 if ( e . target . checked ) {
349- selectedFileHashes . push ( e . target . value ) ;
353+ if ( selectMultiple ) {
354+ const startSelectingFromIndex = collOutput . SelectedPathContents . Files . findIndex (
355+ ( f ) => f . Path === this . state . lastSelectedFileHash ,
356+ ) ;
357+ if ( startSelectingFromIndex === - 1 ) {
358+ throw new Error ( 'should not happen' ) ;
359+ }
360+
361+ for (
362+ let i = startSelectingFromIndex ;
363+ i < collOutput . SelectedPathContents . Files . length ;
364+ ++ i
365+ ) {
366+ const path = collOutput . SelectedPathContents . Files [ i ] . Path ;
367+ if ( selectedFileHashes . indexOf ( path ) === - 1 ) {
368+ selectedFileHashes . push ( path ) ;
369+ }
370+
371+ if ( e . target . value === path ) {
372+ break ;
373+ }
374+ }
375+ } else {
376+ const selected = e . target . value ;
377+ selectedFileHashes . push ( selected ) ;
378+
379+ this . state . lastSelectedFileHash = selected ;
380+ }
350381 }
351382
352383 this . setState ( { selectedFileHashes } ) ;
0 commit comments