mirror of
https://github.com/davidkaya/aryx.git
synced 2026-08-25 20:33:58 +02:00
fix: wire modifier key detection into SessionItem click handler
Ctrl+Click (⌘+Click on Mac) and Shift+Click were not triggering multi-select mode because modifier key detection in handleSessionClick was never called from the actual click chain. Root cause: - SessionItem.handleClick only checked isSelecting state, never inspected modifier keys on the mouse event - ProjectGroup passed onSessionSelect directly (plain navigation), bypassing handleSessionClick entirely - Search results called handleSessionClick with a hardcoded fake event where all modifier keys were false Fix: - Move modifier key detection into SessionItem.handleClick, which receives the real React.MouseEvent with accurate modifier state - Add onEnterSelectionMode and onShiftSelect props to SessionItem - Thread new callbacks through ProjectGroup - Remove dead handleSessionClick function from Sidebar - Fix search results to use the new callback-based approach Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -194,6 +194,8 @@ function SessionItem({
|
|||||||
isSelected,
|
isSelected,
|
||||||
selectionIndex,
|
selectionIndex,
|
||||||
onToggleSelection,
|
onToggleSelection,
|
||||||
|
onEnterSelectionMode,
|
||||||
|
onShiftSelect,
|
||||||
}: {
|
}: {
|
||||||
session: SessionRecord;
|
session: SessionRecord;
|
||||||
workflow?: WorkflowDefinition;
|
workflow?: WorkflowDefinition;
|
||||||
@@ -207,6 +209,8 @@ function SessionItem({
|
|||||||
isSelected?: boolean;
|
isSelected?: boolean;
|
||||||
selectionIndex?: number;
|
selectionIndex?: number;
|
||||||
onToggleSelection?: () => void;
|
onToggleSelection?: () => void;
|
||||||
|
onEnterSelectionMode?: () => void;
|
||||||
|
onShiftSelect?: () => void;
|
||||||
}) {
|
}) {
|
||||||
const isRunning = session.status === 'running';
|
const isRunning = session.status === 'running';
|
||||||
const isError = session.status === 'error';
|
const isError = session.status === 'error';
|
||||||
@@ -216,7 +220,7 @@ function SessionItem({
|
|||||||
const visual = modeVisuals[mode];
|
const visual = modeVisuals[mode];
|
||||||
const ModeIcon = visual.icon;
|
const ModeIcon = visual.icon;
|
||||||
const agentCount = workflow ? resolveWorkflowAgentNodes(workflow).length : 1;
|
const agentCount = workflow ? resolveWorkflowAgentNodes(workflow).length : 1;
|
||||||
const isSelectDisabled = isRunning && isSelecting;
|
const isSelectDisabled = isRunning;
|
||||||
|
|
||||||
const [renameText, setRenameText] = useState(session.title);
|
const [renameText, setRenameText] = useState(session.title);
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
@@ -250,10 +254,25 @@ function SessionItem({
|
|||||||
|
|
||||||
function handleClick(e: React.MouseEvent) {
|
function handleClick(e: React.MouseEvent) {
|
||||||
if (isRenaming) return;
|
if (isRenaming) return;
|
||||||
|
|
||||||
|
// Already in selection mode — toggle or range-select
|
||||||
if (isSelecting) {
|
if (isSelecting) {
|
||||||
if (!isSelectDisabled) onToggleSelection?.();
|
if (isSelectDisabled) return;
|
||||||
|
if (e.shiftKey) {
|
||||||
|
onShiftSelect?.();
|
||||||
|
} else {
|
||||||
|
onToggleSelection?.();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Not in selection mode — check for modifier key to enter it
|
||||||
|
const modKey = isMac ? e.metaKey : e.ctrlKey;
|
||||||
|
if (modKey && !isSelectDisabled) {
|
||||||
|
onEnterSelectionMode?.();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
onSelect();
|
onSelect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,6 +457,8 @@ function ProjectGroup({
|
|||||||
isSelecting,
|
isSelecting,
|
||||||
isSelected,
|
isSelected,
|
||||||
onToggleSelection,
|
onToggleSelection,
|
||||||
|
onEnterSelectionMode,
|
||||||
|
onShiftSelect,
|
||||||
}: {
|
}: {
|
||||||
project: ProjectRecord;
|
project: ProjectRecord;
|
||||||
sessions: SessionRecord[];
|
sessions: SessionRecord[];
|
||||||
@@ -455,6 +476,8 @@ function ProjectGroup({
|
|||||||
isSelecting?: boolean;
|
isSelecting?: boolean;
|
||||||
isSelected?: (sessionId: string) => boolean;
|
isSelected?: (sessionId: string) => boolean;
|
||||||
onToggleSelection?: (sessionId: string) => void;
|
onToggleSelection?: (sessionId: string) => void;
|
||||||
|
onEnterSelectionMode?: (sessionId: string) => void;
|
||||||
|
onShiftSelect?: (sessionId: string) => void;
|
||||||
}){
|
}){
|
||||||
const [expanded, setExpanded] = useState(true);
|
const [expanded, setExpanded] = useState(true);
|
||||||
const isScratchpad = isScratchpadProject(project);
|
const isScratchpad = isScratchpadProject(project);
|
||||||
@@ -592,6 +615,8 @@ function ProjectGroup({
|
|||||||
isSelected={isSelected?.(session.id)}
|
isSelected={isSelected?.(session.id)}
|
||||||
selectionIndex={index}
|
selectionIndex={index}
|
||||||
onToggleSelection={() => onToggleSelection?.(session.id)}
|
onToggleSelection={() => onToggleSelection?.(session.id)}
|
||||||
|
onEnterSelectionMode={() => onEnterSelectionMode?.(session.id)}
|
||||||
|
onShiftSelect={() => onShiftSelect?.(session.id)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{onNewSession ? (
|
{onNewSession ? (
|
||||||
@@ -728,27 +753,10 @@ export function Sidebar({
|
|||||||
[selection.selectedIds, workspace.sessions],
|
[selection.selectedIds, workspace.sessions],
|
||||||
);
|
);
|
||||||
|
|
||||||
function handleSessionClick(sessionId: string, e: React.MouseEvent) {
|
function handleEnterSelectionMode(sessionId: string) {
|
||||||
const modKey = isMac ? e.metaKey : e.ctrlKey;
|
|
||||||
const session = workspace.sessions.find((s) => s.id === sessionId);
|
const session = workspace.sessions.find((s) => s.id === sessionId);
|
||||||
const isRunning = session?.status === 'running';
|
if (session?.status === 'running') return;
|
||||||
|
selection.enterSelectionMode(sessionId);
|
||||||
if (selection.isSelecting) {
|
|
||||||
if (isRunning) return;
|
|
||||||
if (e.shiftKey) {
|
|
||||||
selection.rangeSelect(sessionId, allVisibleIds);
|
|
||||||
} else {
|
|
||||||
selection.toggle(sessionId);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (modKey && !isRunning) {
|
|
||||||
selection.enterSelectionMode(sessionId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
onSessionSelect(sessionId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleToggleSelection(sessionId: string) {
|
function handleToggleSelection(sessionId: string) {
|
||||||
@@ -757,6 +765,12 @@ export function Sidebar({
|
|||||||
selection.toggle(sessionId);
|
selection.toggle(sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleShiftSelect(sessionId: string) {
|
||||||
|
const session = workspace.sessions.find((s) => s.id === sessionId);
|
||||||
|
if (session?.status === 'running') return;
|
||||||
|
selection.rangeSelect(sessionId, allVisibleIds);
|
||||||
|
}
|
||||||
|
|
||||||
const handleBatchArchive = useCallback(() => {
|
const handleBatchArchive = useCallback(() => {
|
||||||
const ids = [...selection.selectedIds];
|
const ids = [...selection.selectedIds];
|
||||||
const isArchived = !allSelectedArchived;
|
const isArchived = !allSelectedArchived;
|
||||||
@@ -873,7 +887,7 @@ export function Sidebar({
|
|||||||
isActive={workspace.selectedSessionId === session.id}
|
isActive={workspace.selectedSessionId === session.id}
|
||||||
isRenaming={renamingSessionId === session.id}
|
isRenaming={renamingSessionId === session.id}
|
||||||
key={session.id}
|
key={session.id}
|
||||||
onSelect={() => handleSessionClick(session.id, { ctrlKey: false, metaKey: false, shiftKey: false } as React.MouseEvent)}
|
onSelect={() => onSessionSelect(session.id)}
|
||||||
onOpenMenu={(e) => handleOpenMenu(session.id, e)}
|
onOpenMenu={(e) => handleOpenMenu(session.id, e)}
|
||||||
onRenameSubmit={(title) => handleRenameSubmit(session.id, title)}
|
onRenameSubmit={(title) => handleRenameSubmit(session.id, title)}
|
||||||
onRenameCancel={() => setRenamingSessionId(undefined)}
|
onRenameCancel={() => setRenamingSessionId(undefined)}
|
||||||
@@ -883,6 +897,8 @@ export function Sidebar({
|
|||||||
isSelected={selection.isSelected(session.id)}
|
isSelected={selection.isSelected(session.id)}
|
||||||
selectionIndex={index}
|
selectionIndex={index}
|
||||||
onToggleSelection={() => handleToggleSelection(session.id)}
|
onToggleSelection={() => handleToggleSelection(session.id)}
|
||||||
|
onEnterSelectionMode={() => handleEnterSelectionMode(session.id)}
|
||||||
|
onShiftSelect={() => handleShiftSelect(session.id)}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
@@ -911,6 +927,8 @@ export function Sidebar({
|
|||||||
isSelecting={selection.isSelecting}
|
isSelecting={selection.isSelecting}
|
||||||
isSelected={selection.isSelected}
|
isSelected={selection.isSelected}
|
||||||
onToggleSelection={handleToggleSelection}
|
onToggleSelection={handleToggleSelection}
|
||||||
|
onEnterSelectionMode={handleEnterSelectionMode}
|
||||||
|
onShiftSelect={handleShiftSelect}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -962,6 +980,8 @@ export function Sidebar({
|
|||||||
isSelecting={selection.isSelecting}
|
isSelecting={selection.isSelecting}
|
||||||
isSelected={selection.isSelected}
|
isSelected={selection.isSelected}
|
||||||
onToggleSelection={handleToggleSelection}
|
onToggleSelection={handleToggleSelection}
|
||||||
|
onEnterSelectionMode={handleEnterSelectionMode}
|
||||||
|
onShiftSelect={handleShiftSelect}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user