66 Trash ,
77 PencilCompose ,
88} from '../icons/icons' ;
9- import { memo , useCallback , useEffect , useMemo , useRef , type ComponentProps } from 'react' ;
9+ import { memo , useCallback , useEffect , useMemo , useRef , type ComponentProps , useState } from 'react' ;
1010import { useOptimisticThreadState } from '@/components/mail/optimistic-thread-state' ;
1111import { focusedIndexAtom , useMailNavigation } from '@/hooks/use-mail-navigation' ;
1212import { Tooltip , TooltipContent , TooltipTrigger } from '@/components/ui/tooltip' ;
@@ -662,6 +662,22 @@ export const MailList = memo(
662662 const [ , setThreadId ] = useQueryState ( 'threadId' ) ;
663663 const [ , setDraftId ] = useQueryState ( 'draftId' ) ;
664664 const [ searchValue , setSearchValue ] = useSearchValue ( ) ;
665+ const [ anchorIndex , setAnchorIndex ] = useState < number | null > ( null ) ;
666+
667+ useEffect ( ( ) => {
668+ const handleKeyDown = ( event : KeyboardEvent ) => {
669+ if ( event . key === 'Escape' ) {
670+ setAnchorIndex ( null ) ;
671+ }
672+ } ;
673+
674+ window . addEventListener ( 'keydown' , handleKeyDown ) ;
675+
676+ return ( ) => {
677+ window . removeEventListener ( 'keydown' , handleKeyDown ) ;
678+ } ;
679+ } , [ setAnchorIndex ] ) ;
680+
665681 const [ { refetch, isLoading, isFetching, isFetchingNextPage, hasNextPage } , items , , loadMore ] =
666682 useThreads ( ) ;
667683 const trpc = useTRPC ( ) ;
@@ -703,23 +719,20 @@ export const MailList = memo(
703719 const getSelectMode = useCallback ( ( ) : MailSelectMode => {
704720 const isAltPressed =
705721 isKeyPressed ( 'Alt' ) || isKeyPressed ( 'AltLeft' ) || isKeyPressed ( 'AltRight' ) ;
706-
707722 const isShiftPressed =
708723 isKeyPressed ( 'Shift' ) || isKeyPressed ( 'ShiftLeft' ) || isKeyPressed ( 'ShiftRight' ) ;
724+ const isCtrlPressed = isKeyPressed ( 'Control' ) || isKeyPressed ( 'Meta' ) ;
709725
710- if ( isKeyPressed ( 'Control' ) || isKeyPressed ( 'Meta' ) ) {
726+ if ( isShiftPressed && ! isCtrlPressed ) {
727+ return 'range' ;
728+ }
729+ if ( isCtrlPressed ) {
711730 return 'mass' ;
712731 }
713-
714732 if ( isAltPressed && isShiftPressed ) {
715733 console . log ( 'Select All Below mode activated' ) ; // Debug log
716734 return 'selectAllBelow' ;
717735 }
718-
719- if ( isShiftPressed ) {
720- return 'range' ;
721- }
722-
723736 return 'single' ;
724737 } , [ isKeyPressed ] ) ;
725738
@@ -734,6 +747,9 @@ export const MailList = memo(
734747
735748 setMail ( ( prevMail ) => {
736749 const mail = prevMail ;
750+ const clickedIndex = itemsRef . current . findIndex ( ( item ) => item . id === itemId ) ;
751+ if ( clickedIndex === - 1 ) return mail ;
752+
737753 switch ( currentMode ) {
738754 case 'mass' : {
739755 const newSelected = mail . bulkSelected . includes ( itemId )
@@ -761,8 +777,16 @@ export const MailList = memo(
761777 return { ...mail , bulkSelected : [ itemId ] } ;
762778 }
763779 case 'range' : {
764- console . log ( 'Range selection mode - not fully implemented' ) ;
765- return { ...mail , bulkSelected : [ itemId ] } ;
780+ console . log ( 'Range selection mode' ) ;
781+ if ( anchorIndex === null ) {
782+ return { ...mail , bulkSelected : [ itemId ] } ;
783+ }
784+ const start = Math . min ( anchorIndex , clickedIndex ) ;
785+ const end = Math . max ( anchorIndex , clickedIndex ) ;
786+ const rangeIds = itemsRef . current . slice ( start , end + 1 ) . map ( ( item ) => item . id ) ;
787+ const newSelected = [ ...new Set ( [ ...mail . bulkSelected , ...rangeIds ] ) ] ;
788+
789+ return { ...mail , bulkSelected : newSelected } ;
766790 }
767791 default : {
768792 console . log ( 'Single selection mode' ) ;
@@ -771,7 +795,7 @@ export const MailList = memo(
771795 }
772796 } ) ;
773797 } ,
774- [ getSelectMode , setMail ] ,
798+ [ getSelectMode , setMail , anchorIndex ] ,
775799 ) ;
776800
777801 const [ , setFocusedIndex ] = useAtom ( focusedIndexAtom ) ;
@@ -784,6 +808,11 @@ export const MailList = memo(
784808 console . log ( 'Mail click with mode:' , mode ) ;
785809
786810 if ( mode !== 'single' ) {
811+ const messageThreadId = message . threadId ?? message . id ;
812+ const clickedIndex = itemsRef . current . findIndex ( ( item ) => item . id === messageThreadId ) ;
813+ if ( clickedIndex !== - 1 && mode !== 'range' ) {
814+ setAnchorIndex ( clickedIndex ) ;
815+ }
787816 return handleSelectMail ( message ) ;
788817 }
789818
0 commit comments