refactor(web): extract document drag listeners
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { attachDocumentMouseDrag } from "./timelineDocumentDrag.js";
|
||||
|
||||
describe("timelineDocumentDrag", () => {
|
||||
it("registers move and up listeners and removes both during cleanup", () => {
|
||||
const addEventListener = vi.fn();
|
||||
const removeEventListener = vi.fn();
|
||||
const onMove = vi.fn();
|
||||
const onUp = vi.fn();
|
||||
|
||||
const cleanup = attachDocumentMouseDrag({ addEventListener, removeEventListener }, onMove, onUp);
|
||||
|
||||
expect(addEventListener).toHaveBeenCalledTimes(2);
|
||||
expect(addEventListener).toHaveBeenNthCalledWith(1, "mousemove", onMove);
|
||||
expect(addEventListener).toHaveBeenNthCalledWith(2, "mouseup", onUp);
|
||||
|
||||
cleanup();
|
||||
|
||||
expect(removeEventListener).toHaveBeenCalledTimes(2);
|
||||
expect(removeEventListener).toHaveBeenNthCalledWith(1, "mousemove", onMove);
|
||||
expect(removeEventListener).toHaveBeenNthCalledWith(2, "mouseup", onUp);
|
||||
});
|
||||
|
||||
it("keeps cleanup idempotent from the helper perspective", () => {
|
||||
const removeEventListener = vi.fn();
|
||||
|
||||
const cleanup = attachDocumentMouseDrag(
|
||||
{
|
||||
addEventListener: vi.fn(),
|
||||
removeEventListener,
|
||||
},
|
||||
vi.fn(),
|
||||
vi.fn(),
|
||||
);
|
||||
|
||||
cleanup();
|
||||
cleanup();
|
||||
|
||||
expect(removeEventListener).toHaveBeenCalledTimes(4);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
type MouseDragDocumentLike = {
|
||||
addEventListener: (type: "mousemove" | "mouseup", listener: (event: MouseEvent) => void) => void;
|
||||
removeEventListener: (type: "mousemove" | "mouseup", listener: (event: MouseEvent) => void) => void;
|
||||
};
|
||||
|
||||
export function attachDocumentMouseDrag(
|
||||
doc: MouseDragDocumentLike,
|
||||
onMove: (event: MouseEvent) => void,
|
||||
onUp: (event: MouseEvent) => void,
|
||||
): () => void {
|
||||
function cleanup() {
|
||||
doc.removeEventListener("mousemove", onMove);
|
||||
doc.removeEventListener("mouseup", onUp);
|
||||
}
|
||||
|
||||
doc.addEventListener("mousemove", onMove);
|
||||
doc.addEventListener("mouseup", onUp);
|
||||
return cleanup;
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
updateAllocationMultiDrag,
|
||||
} from "./timelineAllocationMultiDrag.js";
|
||||
import { createAllocationDragState } from "./timelineAllocationDragState.js";
|
||||
import { attachDocumentMouseDrag } from "./timelineDocumentDrag.js";
|
||||
import { buildProjectShiftMutationInput, createProjectDragState } from "./timelineProjectDrag.js";
|
||||
import {
|
||||
createMultiSelectState,
|
||||
@@ -559,12 +560,7 @@ export function useTimelineDrag({
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
document.addEventListener("mousemove", handleMove);
|
||||
document.addEventListener("mouseup", handleUp);
|
||||
projectDragCleanupRef.current = () => {
|
||||
document.removeEventListener("mousemove", handleMove);
|
||||
document.removeEventListener("mouseup", handleUp);
|
||||
};
|
||||
projectDragCleanupRef.current = attachDocumentMouseDrag(document, handleMove, handleUp);
|
||||
},
|
||||
[finalizeProjectDrag, setProjectPreviewTargets, updateProjectDragPosition],
|
||||
);
|
||||
@@ -672,12 +668,7 @@ export function useTimelineDrag({
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("mousemove", handleMultiMove);
|
||||
document.addEventListener("mouseup", handleMultiUp);
|
||||
multiSelectCleanupRef.current = () => {
|
||||
document.removeEventListener("mousemove", handleMultiMove);
|
||||
document.removeEventListener("mouseup", handleMultiUp);
|
||||
};
|
||||
multiSelectCleanupRef.current = attachDocumentMouseDrag(document, handleMultiMove, handleMultiUp);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -796,12 +787,7 @@ export function useTimelineDrag({
|
||||
setAllocDragState(INITIAL_ALLOC_DRAG);
|
||||
}
|
||||
|
||||
document.addEventListener("mousemove", handleMove);
|
||||
document.addEventListener("mouseup", handleUp);
|
||||
allocDragCleanupRef.current = () => {
|
||||
document.removeEventListener("mousemove", handleMove);
|
||||
document.removeEventListener("mouseup", handleUp);
|
||||
};
|
||||
allocDragCleanupRef.current = attachDocumentMouseDrag(document, handleMove, handleUp);
|
||||
},
|
||||
[
|
||||
clearPendingOptimisticAllocation,
|
||||
@@ -943,12 +929,7 @@ export function useTimelineDrag({
|
||||
setMultiSelectState(finished);
|
||||
}
|
||||
|
||||
document.addEventListener("mousemove", handleMove);
|
||||
document.addEventListener("mouseup", handleUp);
|
||||
multiSelectCleanupRef.current = () => {
|
||||
document.removeEventListener("mousemove", handleMove);
|
||||
document.removeEventListener("mouseup", handleUp);
|
||||
};
|
||||
multiSelectCleanupRef.current = attachDocumentMouseDrag(document, handleMove, handleUp);
|
||||
}, []);
|
||||
|
||||
const clearMultiSelect = useCallback(() => {
|
||||
|
||||
Reference in New Issue
Block a user