chore: add comment for explain selectElementRange
This commit is contained in:
parent
97db7aa21c
commit
e223348d47
|
|
@ -83,10 +83,10 @@ export function useElementSelection() {
|
|||
* Merges elements into the current selection, deduplicating by identity.
|
||||
* Used for additive box-select where the pre-drag selection is preserved.
|
||||
*/
|
||||
const mergeElementsIntoSelection = useCallback(
|
||||
({ elements }: { elements: ElementRef[] }) => {
|
||||
const merged = [
|
||||
...selectedElements.filter(
|
||||
const mergeElementsIntoSelection = useCallback(
|
||||
({ elements }: { elements: ElementRef[] }) => {
|
||||
const merged = [
|
||||
...selectedElements.filter(
|
||||
(selectedElement) =>
|
||||
!elements.some(
|
||||
(element) =>
|
||||
|
|
@ -98,74 +98,78 @@ export function useElementSelection() {
|
|||
];
|
||||
editor.selection.setSelectedElements({ elements: merged });
|
||||
},
|
||||
[selectedElements, editor],
|
||||
);
|
||||
|
||||
const selectElementRange = useCallback(
|
||||
({
|
||||
anchor,
|
||||
target,
|
||||
}: {
|
||||
anchor?: ElementRef | null;
|
||||
target: ElementRef;
|
||||
}) => {
|
||||
const tracks = editor.scenes.getActiveScene().tracks;
|
||||
const track = [...tracks.overlay, tracks.main, ...tracks.audio].find(
|
||||
(candidate) => candidate.id === target.trackId,
|
||||
);
|
||||
const rangeAnchor =
|
||||
anchor?.trackId === target.trackId
|
||||
? anchor
|
||||
: selectedElements
|
||||
.slice()
|
||||
.reverse()
|
||||
.find((element) => element.trackId === target.trackId);
|
||||
|
||||
if (!track || !rangeAnchor) {
|
||||
const elements = [target];
|
||||
editor.selection.setSelectedElements({ elements });
|
||||
return elements;
|
||||
}
|
||||
|
||||
const orderedElements = track.elements
|
||||
.map((element, index) => ({ element, index }))
|
||||
.sort((a, b) => {
|
||||
if (a.element.startTime !== b.element.startTime) {
|
||||
return a.element.startTime - b.element.startTime;
|
||||
}
|
||||
return a.index - b.index;
|
||||
});
|
||||
const anchorIndex = orderedElements.findIndex(
|
||||
({ element }) => element.id === rangeAnchor.elementId,
|
||||
);
|
||||
const targetIndex = orderedElements.findIndex(
|
||||
({ element }) => element.id === target.elementId,
|
||||
);
|
||||
|
||||
if (anchorIndex === -1 || targetIndex === -1) {
|
||||
const elements = [target];
|
||||
editor.selection.setSelectedElements({ elements });
|
||||
return elements;
|
||||
}
|
||||
|
||||
const start = Math.min(anchorIndex, targetIndex);
|
||||
const end = Math.max(anchorIndex, targetIndex);
|
||||
const elements = orderedElements
|
||||
.slice(start, end + 1)
|
||||
.map(({ element }) => ({
|
||||
trackId: target.trackId,
|
||||
elementId: element.id,
|
||||
}));
|
||||
|
||||
editor.selection.setSelectedElements({ elements });
|
||||
return elements;
|
||||
},
|
||||
[selectedElements, editor],
|
||||
);
|
||||
|
||||
/**
|
||||
* Handles click interaction on an element.
|
||||
* - Regular click: select only this element
|
||||
[selectedElements, editor],
|
||||
);
|
||||
|
||||
/**
|
||||
* Selects every element between the anchor and target on the same timeline row.
|
||||
* Falls back to selecting only the target when no same-row anchor exists.
|
||||
*/
|
||||
const selectElementRange = useCallback(
|
||||
({
|
||||
anchor,
|
||||
target,
|
||||
}: {
|
||||
anchor?: ElementRef | null;
|
||||
target: ElementRef;
|
||||
}) => {
|
||||
const tracks = editor.scenes.getActiveScene().tracks;
|
||||
const track = [...tracks.overlay, tracks.main, ...tracks.audio].find(
|
||||
(candidate) => candidate.id === target.trackId,
|
||||
);
|
||||
const rangeAnchor =
|
||||
anchor?.trackId === target.trackId
|
||||
? anchor
|
||||
: selectedElements
|
||||
.slice()
|
||||
.reverse()
|
||||
.find((element) => element.trackId === target.trackId);
|
||||
|
||||
if (!track || !rangeAnchor) {
|
||||
const elements = [target];
|
||||
editor.selection.setSelectedElements({ elements });
|
||||
return elements;
|
||||
}
|
||||
|
||||
const orderedElements = track.elements
|
||||
.map((element, index) => ({ element, index }))
|
||||
.sort((a, b) => {
|
||||
if (a.element.startTime !== b.element.startTime) {
|
||||
return a.element.startTime - b.element.startTime;
|
||||
}
|
||||
return a.index - b.index;
|
||||
});
|
||||
const anchorIndex = orderedElements.findIndex(
|
||||
({ element }) => element.id === rangeAnchor.elementId,
|
||||
);
|
||||
const targetIndex = orderedElements.findIndex(
|
||||
({ element }) => element.id === target.elementId,
|
||||
);
|
||||
|
||||
if (anchorIndex === -1 || targetIndex === -1) {
|
||||
const elements = [target];
|
||||
editor.selection.setSelectedElements({ elements });
|
||||
return elements;
|
||||
}
|
||||
|
||||
const start = Math.min(anchorIndex, targetIndex);
|
||||
const end = Math.max(anchorIndex, targetIndex);
|
||||
const elements = orderedElements
|
||||
.slice(start, end + 1)
|
||||
.map(({ element }) => ({
|
||||
trackId: target.trackId,
|
||||
elementId: element.id,
|
||||
}));
|
||||
|
||||
editor.selection.setSelectedElements({ elements });
|
||||
return elements;
|
||||
},
|
||||
[selectedElements, editor],
|
||||
);
|
||||
|
||||
/**
|
||||
* Handles click interaction on an element.
|
||||
* - Regular click: select only this element
|
||||
* - Multi-key click (Ctrl/Cmd): toggle this element in selection
|
||||
*/
|
||||
const handleElementClick = useCallback(
|
||||
|
|
@ -186,13 +190,13 @@ export function useElementSelection() {
|
|||
return {
|
||||
selectedElements,
|
||||
isElementSelected,
|
||||
selectElement,
|
||||
setElementSelection,
|
||||
mergeElementsIntoSelection,
|
||||
selectElementRange,
|
||||
addElementToSelection,
|
||||
removeElementFromSelection,
|
||||
toggleElementSelection,
|
||||
selectElement,
|
||||
setElementSelection,
|
||||
mergeElementsIntoSelection,
|
||||
selectElementRange,
|
||||
addElementToSelection,
|
||||
removeElementFromSelection,
|
||||
toggleElementSelection,
|
||||
clearElementSelection,
|
||||
handleElementClick,
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue