Skip to content

Commit 424f913

Browse files
ayushsharma74cubic-dev-ai[bot]MrgSub
authored
feat: add range selection support for thread list (#1856)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> Co-authored-by: Adam <[email protected]>
1 parent 9d3660d commit 424f913

File tree

1 file changed

+41
-12
lines changed

1 file changed

+41
-12
lines changed

apps/mail/components/mail/mail-list.tsx

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
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';
1010
import { useOptimisticThreadState } from '@/components/mail/optimistic-thread-state';
1111
import { focusedIndexAtom, useMailNavigation } from '@/hooks/use-mail-navigation';
1212
import { 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

Comments
 (0)