refactor: Unify document selection and drag interactions by replacing stack-specific callbacks and simplifying drag state.
This commit is contained in:
@@ -42,6 +42,7 @@ export interface PointerIntent {
|
||||
clickSelectionApplied: boolean;
|
||||
stackSelectionApplied: boolean;
|
||||
longPressTriggered: boolean;
|
||||
optimisticSelection: string[];
|
||||
}
|
||||
|
||||
export const createPointerIntent = ({
|
||||
@@ -61,9 +62,9 @@ export const createPointerIntent = ({
|
||||
|
||||
if (metaKey) {
|
||||
clickAction = CLICK_ACTIONS.addStack;
|
||||
dragAction = DRAG_ACTIONS.dragSelectStack;
|
||||
dragAction = DRAG_ACTIONS.dragSelection;
|
||||
} else if (alreadySelected) {
|
||||
clickAction = CLICK_ACTIONS.selectSingle;
|
||||
clickAction = CLICK_ACTIONS.openDetail;
|
||||
dragAction = selectionCount > 1 ? DRAG_ACTIONS.dragSelection : DRAG_ACTIONS.dragSelectSingle;
|
||||
} else {
|
||||
clickAction = CLICK_ACTIONS.selectSingle;
|
||||
@@ -74,8 +75,23 @@ export const createPointerIntent = ({
|
||||
? stackHits.map((value) => String(value))
|
||||
: [String(doc.id)];
|
||||
|
||||
const stackDocIdsForDrag = dragAction === DRAG_ACTIONS.dragSelectStack ? stackList : null;
|
||||
const stackDocIdsForClick = clickAction === CLICK_ACTIONS.addStack ? stackList : null;
|
||||
const stackDocIdsForDrag = metaKey ? stackList : null;
|
||||
|
||||
// Calculate optimistic selection
|
||||
let optimisticSelection: string[] = [];
|
||||
if (metaKey) {
|
||||
// Additive selection (stack or single)
|
||||
const currentSelection = new Set(selectedDocumentIds);
|
||||
stackList.forEach(id => currentSelection.add(id));
|
||||
optimisticSelection = Array.from(currentSelection);
|
||||
} else if (alreadySelected) {
|
||||
// Already selected: keep current selection
|
||||
optimisticSelection = [...selectedDocumentIds];
|
||||
} else {
|
||||
// New single selection
|
||||
optimisticSelection = [doc.id];
|
||||
}
|
||||
|
||||
return {
|
||||
docId: doc.id,
|
||||
@@ -90,33 +106,53 @@ export const createPointerIntent = ({
|
||||
stackDocIdsForDrag,
|
||||
stackDocIdsForClick,
|
||||
stackReplaceOnClick: clickAction === CLICK_ACTIONS.addStack,
|
||||
stackReplaceOnDrag: dragAction === DRAG_ACTIONS.dragSelectStack,
|
||||
stackReplaceOnDrag: false,
|
||||
clickSelectionApplied: false,
|
||||
stackSelectionApplied: false,
|
||||
longPressTriggered: false,
|
||||
optimisticSelection,
|
||||
};
|
||||
};
|
||||
|
||||
export const applyClickPlanImmediately = ({ intent, event, onEntryPointer, onDocumentStackSelect }: {
|
||||
export const applyClickPlanImmediately = ({ intent, event, onEntryPointer, onDocumentStackSelect, onSelect }: {
|
||||
intent: PointerIntent;
|
||||
event?: unknown;
|
||||
onEntryPointer?: (descriptor: unknown, event?: unknown) => void;
|
||||
onDocumentStackSelect?: (docIds: string[], event?: unknown, options?: { replace?: boolean }) => void;
|
||||
onSelect?: (descriptor: unknown, event?: unknown) => void;
|
||||
}) => {
|
||||
switch (intent.clickAction) {
|
||||
case CLICK_ACTIONS.selectSingle:
|
||||
case CLICK_ACTIONS.addCard:
|
||||
safeInvoke(onEntryPointer, intent.entryDescriptor, event);
|
||||
if (onSelect) {
|
||||
safeInvoke(onSelect, intent.entryDescriptor, event);
|
||||
} else {
|
||||
safeInvoke(onEntryPointer, intent.entryDescriptor, event);
|
||||
}
|
||||
intent.clickSelectionApplied = true;
|
||||
break;
|
||||
case CLICK_ACTIONS.addStack:
|
||||
if (Array.isArray(intent.stackDocIdsForClick) && intent.stackDocIdsForClick.length > 0) {
|
||||
safeInvoke(
|
||||
onDocumentStackSelect,
|
||||
intent.stackDocIdsForClick,
|
||||
event,
|
||||
{ replace: intent.stackReplaceOnClick },
|
||||
);
|
||||
// Use onSelect for stack selection (batch)
|
||||
if (onSelect) {
|
||||
// Map docIds to descriptors if necessary, or just pass IDs if onSelect handles it.
|
||||
// The current onSelect adapter in DesktopWorkspace expects { id } objects or just IDs?
|
||||
// Let's assume it expects descriptors like selectSingle.
|
||||
const descriptors = intent.stackDocIdsForClick.map(id => ({
|
||||
type: 'document',
|
||||
id,
|
||||
key: `document:${id}`,
|
||||
}));
|
||||
safeInvoke(onSelect, descriptors, event);
|
||||
} else {
|
||||
// Fallback to legacy if onSelect not provided (shouldn't happen in new flow)
|
||||
safeInvoke(
|
||||
onDocumentStackSelect,
|
||||
intent.stackDocIdsForClick,
|
||||
event,
|
||||
{ replace: intent.stackReplaceOnClick },
|
||||
);
|
||||
}
|
||||
intent.clickSelectionApplied = true;
|
||||
intent.stackSelectionApplied = true;
|
||||
}
|
||||
@@ -128,17 +164,18 @@ export const applyClickPlanImmediately = ({ intent, event, onEntryPointer, onDoc
|
||||
}
|
||||
};
|
||||
|
||||
export const finalizeClickSelection = ({ intent, event, onEntryPointer, onDocumentStackSelect }: {
|
||||
export const finalizeClickSelection = ({ intent, event, onEntryPointer, onDocumentStackSelect, onSelect }: {
|
||||
intent: PointerIntent;
|
||||
event?: unknown;
|
||||
onEntryPointer?: (descriptor: unknown, event?: unknown) => void;
|
||||
onDocumentStackSelect?: (docIds: string[], event?: unknown, options?: { replace?: boolean }) => void;
|
||||
onSelect?: (descriptor: unknown, event?: unknown) => void;
|
||||
}) => {
|
||||
if (!intent || intent.clickSelectionApplied) {
|
||||
return;
|
||||
}
|
||||
|
||||
applyClickPlanImmediately({ intent, event, onEntryPointer, onDocumentStackSelect });
|
||||
applyClickPlanImmediately({ intent, event, onEntryPointer, onDocumentStackSelect, onSelect });
|
||||
};
|
||||
|
||||
export const applyLongPressSelection = ({ intent, stackDocIds, syntheticEvent, onDocumentStackSelect }: {
|
||||
|
||||
Reference in New Issue
Block a user