@@ -76,6 +76,8 @@ const SectionHeading = styled('h2')`
7676
7777const ESCAPE_KEY = 27
7878const CTRL_KEY = 17
79+ const SHIFT_KEY = 16
80+ const A_KEY = 65
7981
8082const Thumbnails = ( {
8183 photoSections,
@@ -88,6 +90,8 @@ const Thumbnails = ({
8890 const history = useHistory ( )
8991 const [ selected , setSelected ] = useState ( [ ] )
9092 const [ ctrlKeyPressed , setCtrlKeyPressed ] = useState ( false )
93+ const [ shiftKeyPressed , setShiftKeyPressed ] = useState ( false )
94+ const [ lastSelectedId , setLastSelectedId ] = useState ( null )
9195
9296 const [ removePhotosFromAlbum ] = useMutation ( REMOVE_PHOTOS_FROM_ALBUM )
9397 const [ setPhotosDeleted ] = useMutation ( SET_PHOTOS_DELETED )
@@ -163,11 +167,47 @@ const Thumbnails = ({
163167 return null
164168 }
165169
166- const addRemoveItem = ( id ) => {
170+ // Get flat array of all photo IDs in display order
171+ const getAllPhotoIds = ( ) => {
172+ const ids = [ ]
173+ if ( ! photoSections ) return ids
174+ for ( const section of photoSections ) {
175+ for ( const segment of section . segments ) {
176+ for ( const photo of segment . photos ) {
177+ if ( mode !== 'ALBUMS' ) {
178+ ids . push ( photo . id )
179+ }
180+ }
181+ }
182+ }
183+ return ids
184+ }
185+
186+ const addRemoveItem = ( id , isShiftClick = false ) => {
187+ if ( isShiftClick && lastSelectedId && lastSelectedId !== id ) {
188+ // Range selection: select all items between lastSelectedId and id
189+ const allIds = getAllPhotoIds ( )
190+ const lastIndex = allIds . indexOf ( lastSelectedId )
191+ const currentIndex = allIds . indexOf ( id )
192+
193+ if ( lastIndex !== - 1 && currentIndex !== - 1 ) {
194+ const startIndex = Math . min ( lastIndex , currentIndex )
195+ const endIndex = Math . max ( lastIndex , currentIndex )
196+ const rangeIds = allIds . slice ( startIndex , endIndex + 1 )
197+
198+ // Add range to existing selection (union)
199+ const newSelected = [ ...new Set ( [ ...selected , ...rangeIds ] ) ]
200+ setSelected ( newSelected )
201+ return
202+ }
203+ }
204+
205+ // Normal toggle behavior for ctrl-click or single click
167206 let ids = [ ...selected ]
168207 const index = ids . indexOf ( id )
169208 index > - 1 ? ids . splice ( index , 1 ) : ids . push ( id )
170209 setSelected ( ids )
210+ setLastSelectedId ( id )
171211 }
172212
173213 const bind = useLongPress (
@@ -196,10 +236,24 @@ const Thumbnails = ({
196236 switch ( event . keyCode ) {
197237 case ESCAPE_KEY :
198238 setSelected ( [ ] )
239+ setLastSelectedId ( null )
199240 break
200241 case CTRL_KEY :
201242 setCtrlKeyPressed ( true )
202243 break
244+ case SHIFT_KEY :
245+ setShiftKeyPressed ( true )
246+ break
247+ case A_KEY :
248+ if ( event . ctrlKey || event . metaKey ) {
249+ event . preventDefault ( )
250+ const allIds = getAllPhotoIds ( )
251+ setSelected ( allIds )
252+ if ( allIds . length > 0 ) {
253+ setLastSelectedId ( allIds [ allIds . length - 1 ] )
254+ }
255+ }
256+ break
203257 default :
204258 break
205259 }
@@ -210,6 +264,9 @@ const Thumbnails = ({
210264 case CTRL_KEY :
211265 setCtrlKeyPressed ( false )
212266 break
267+ case SHIFT_KEY :
268+ setShiftKeyPressed ( false )
269+ break
213270 default :
214271 break
215272 }
@@ -222,14 +279,15 @@ const Thumbnails = ({
222279 document . removeEventListener ( 'keydown' , handleKeyDown )
223280 document . removeEventListener ( 'keyup' , handleKeyUp )
224281 }
225- } , [ ] )
282+ } , [ photoSections , mode ] )
226283
227- const onMouseDown = ctrlKeyPressed
228- ? ( e ) => {
229- const id = getNode ( e . target ) . getAttribute ( 'data-id' )
230- addRemoveItem ( id )
231- }
232- : bind . onMouseDown
284+ const onMouseDown =
285+ ctrlKeyPressed || shiftKeyPressed
286+ ? ( e ) => {
287+ const id = getNode ( e . target ) . getAttribute ( 'data-id' )
288+ addRemoveItem ( id , shiftKeyPressed )
289+ }
290+ : bind . onMouseDown
233291
234292 return (
235293 < >
@@ -281,7 +339,7 @@ const Thumbnails = ({
281339 starRating = { photo . starRating }
282340 rotation = { photo . rotation }
283341 selected = { selected . indexOf ( photo . id ) > - 1 }
284- selectable = { selected . length > 0 || ctrlKeyPressed }
342+ selectable = { selected . length > 0 || ctrlKeyPressed || shiftKeyPressed }
285343 mode = { mode }
286344 rateable = { rateable }
287345 { ...bind }
0 commit comments