fix(frontend): shift-select in gesture direction, not grid order
Shift range-select normalized the range with Math.min/Math.max and always iterated ascending, so the selection's insertion order (which the Set preserves and which carries through to e.g. pool add order) ignored the gesture direction. Iterate anchor → target instead via a shared selectRange helper, so selecting first→last and last→first yield correspondingly ordered selections. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -94,15 +94,22 @@
|
|||||||
// Select via the keyboard: a plain press toggles the focused card and drops the
|
// Select via the keyboard: a plain press toggles the focused card and drops the
|
||||||
// range anchor there; a Shift press selects everything from the anchor to the
|
// range anchor there; a Shift press selects everything from the anchor to the
|
||||||
// focused card — the same model as Shift+click on the grid.
|
// focused card — the same model as Shift+click on the grid.
|
||||||
|
// Select an inclusive index range in gesture direction (anchor → target) so the
|
||||||
|
// selection's insertion order follows how the user swept, not grid order. The
|
||||||
|
// Set preserves insertion order, so this is what later carries through to e.g.
|
||||||
|
// the order files land in a pool.
|
||||||
|
function selectRange(anchorIdx: number, targetIdx: number) {
|
||||||
|
const step = targetIdx >= anchorIdx ? 1 : -1;
|
||||||
|
for (let i = anchorIdx; i !== targetIdx + step; i += step) {
|
||||||
|
if (files[i]?.id) selectionStore.select(files[i].id!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function selectFocused(range: boolean) {
|
function selectFocused(range: boolean) {
|
||||||
const idx = focusedId ? files.findIndex((f) => f.id === focusedId) : -1;
|
const idx = focusedId ? files.findIndex((f) => f.id === focusedId) : -1;
|
||||||
if (idx < 0) return;
|
if (idx < 0) return;
|
||||||
if (range && lastSelectedIdx !== null) {
|
if (range && lastSelectedIdx !== null) {
|
||||||
const from = Math.min(lastSelectedIdx, idx);
|
selectRange(lastSelectedIdx, idx);
|
||||||
const to = Math.max(lastSelectedIdx, idx);
|
|
||||||
for (let i = from; i <= to; i++) {
|
|
||||||
if (files[i]?.id) selectionStore.select(files[i].id!);
|
|
||||||
}
|
|
||||||
} else if (files[idx]?.id) {
|
} else if (files[idx]?.id) {
|
||||||
selectionStore.toggle(files[idx].id!);
|
selectionStore.toggle(files[idx].id!);
|
||||||
}
|
}
|
||||||
@@ -634,12 +641,8 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (e.shiftKey && lastSelectedIdx !== null) {
|
if (e.shiftKey && lastSelectedIdx !== null) {
|
||||||
// Range-select between lastSelectedIdx and idx (desktop)
|
// Range-select from the anchor toward idx (desktop), in gesture order.
|
||||||
const from = Math.min(lastSelectedIdx, idx);
|
selectRange(lastSelectedIdx, idx);
|
||||||
const to = Math.max(lastSelectedIdx, idx);
|
|
||||||
for (let i = from; i <= to; i++) {
|
|
||||||
if (files[i]?.id) selectionStore.select(files[i].id!);
|
|
||||||
}
|
|
||||||
lastSelectedIdx = idx;
|
lastSelectedIdx = idx;
|
||||||
} else {
|
} else {
|
||||||
if (file.id) selectionStore.toggle(file.id);
|
if (file.id) selectionStore.toggle(file.id);
|
||||||
|
|||||||
Reference in New Issue
Block a user