diff options
Diffstat (limited to 'src/client/util/DragManager.ts')
-rw-r--r-- | src/client/util/DragManager.ts | 70 |
1 files changed, 39 insertions, 31 deletions
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index c9c499fff..09b463c2f 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -6,8 +6,8 @@ import { PrefetchProxy } from "../../fields/Proxy"; import { listSpec } from "../../fields/Schema"; import { SchemaHeaderField } from "../../fields/SchemaHeaderField"; import { ScriptField } from "../../fields/ScriptField"; -import { Cast, NumCast, ScriptCast, StrCast } from "../../fields/Types"; -import { emptyFunction } from "../../Utils"; +import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../fields/Types"; +import { emptyFunction, Utils } from "../../Utils"; import { Docs, DocUtils } from "../documents/Documents"; import * as globalCssVariables from "../views/global/globalCssVariables.scss"; import { DocumentView } from "../views/nodes/DocumentView"; @@ -56,12 +56,7 @@ export function SetupDrag( if (e.shiftKey) { e.persist(); const dragDoc = await docFunc(); - dragDoc && DragManager.StartWindowDrag?.({ - pageX: e.pageX, - pageY: e.pageY, - preventDefault: emptyFunction, - button: 0 - }, [dragDoc]); + dragDoc && DragManager.StartWindowDrag?.(e, [dragDoc]); } else { document.addEventListener("pointermove", onRowMove); document.addEventListener("pointerup", onRowUp); @@ -74,8 +69,11 @@ export function SetupDrag( export namespace DragManager { let dragDiv: HTMLDivElement; let dragLabel: HTMLDivElement; - export let StartWindowDrag: Opt<((e: any, dragDocs: Doc[]) => void)> = undefined; + export let StartWindowDrag: Opt<((e: { pageX: number, pageY: number }, dragDocs: Doc[], finishDrag?: (aborted: boolean) => void) => void)>; + export let CompleteWindowDrag: Opt<(aborted: boolean) => void>; + export function GetRaiseWhenDragged() { return BoolCast(Doc.UserDoc()._raiseWhenDragged); } + export function SetRaiseWhenDragged(val:boolean) { Doc.UserDoc()._raiseWhenDragged = val } export function Root() { const root = document.getElementById("root"); if (!root) { @@ -225,10 +223,13 @@ export namespace DragManager { if (docDragData && !docDragData.droppedDocuments.length) { docDragData.dropAction = dragData.userDropAction || dragData.dropAction; docDragData.droppedDocuments = - await Promise.all(dragData.draggedDocuments.map(async d => !dragData.isDocDecorationMove && !dragData.userDropAction && ScriptCast(d.onDragStart) ? addAudioTag(ScriptCast(d.onDragStart).script.run({ this: d }).result) : - docDragData.dropAction === "alias" ? Doc.MakeAlias(d) : - docDragData.dropAction === "proto" ? Doc.GetProto(d) : - docDragData.dropAction === "copy" ? (await Doc.MakeClone(d)).clone : d)); + await Promise.all(dragData.draggedDocuments.map(async d => + !dragData.isDocDecorationMove && !dragData.userDropAction && ScriptCast(d.onDragStart) ? + addAudioTag(ScriptCast(d.onDragStart).script.run({ this: d }).result) : + docDragData.dropAction === "alias" ? Doc.MakeAlias(d) : + docDragData.dropAction === "proto" ? Doc.GetProto(d) : + docDragData.dropAction === "copy" ? + (await Doc.MakeClone(d)).clone : d)); !["same", "proto"].includes(docDragData.dropAction as any) && docDragData.droppedDocuments.forEach((drop: Doc, i: number) => { const dragProps = Cast(dragData.draggedDocuments[i].removeDropProperties, listSpec("string"), []); const remProps = (dragData?.removeDropProperties || []).concat(Array.from(dragProps)); @@ -281,7 +282,7 @@ export namespace DragManager { SnappingManager.setSnapLines(horizLines, vertLines); } export function snapDragAspect(dragPt: number[], snapAspect: number) { - let closest = NumCast(Doc.UserDoc()["constants-snapThreshold"], 10); + let closest = Utils.SNAP_THRESHOLD; let near = dragPt; const intersect = (x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number, dragx: number, dragy: number) => { if ((x1 === x2 && y1 === y2) || (x3 === x4 && y3 === y4)) return undefined; // Check if none of the lines are of length 0 @@ -316,7 +317,7 @@ export namespace DragManager { } // snap to the active snap lines - if oneAxis is set (eg, for maintaining aspect ratios), then it only snaps to the nearest horizontal/vertical line export function snapDrag(e: PointerEvent, xFromLeft: number, yFromTop: number, xFromRight: number, yFromBottom: number) { - const snapThreshold = NumCast(Doc.UserDoc()["constants-snapThreshold"], 10); + const snapThreshold = Utils.SNAP_THRESHOLD; const snapVal = (pts: number[], drag: number, snapLines: number[]) => { if (snapLines.length) { const offs = [pts[0], (pts[0] - pts[1]) / 2, -pts[1]]; // offsets from drag pt @@ -383,8 +384,8 @@ export namespace DragManager { } } const rect = ele.getBoundingClientRect(); - const scaleX = rect.width / ele.offsetWidth; - const scaleY = ele.offsetHeight ? rect.height / ele.offsetHeight : scaleX; + const scaleX = rect.width / (ele.offsetWidth || rect.width); + const scaleY = ele.offsetHeight ? rect.height / (ele.offsetHeight || rect.height) : scaleX; elesCont.left = Math.min(rect.left, elesCont.left); elesCont.top = Math.min(rect.top, elesCont.top); @@ -408,7 +409,7 @@ export namespace DragManager { Array.from(pdfBox).filter(pb => pb.width && pb.height).map((pb, i) => pb.getContext('2d')!.drawImage(pdfBoxSrc[i], 0, 0)); } [dragElement, ...Array.from(dragElement.getElementsByTagName('*'))].forEach(ele => - ele.hasAttribute("style") && ((ele as any).style.pointerEvents = "none")); + (ele as any).style && ((ele as any).style.pointerEvents = "none")); dragDiv.appendChild(dragElement); if (dragElement !== ele) { @@ -453,24 +454,29 @@ export namespace DragManager { SnappingManager.clearSnapLines(); batch.end(); }); - const moveHandler = async (e: PointerEvent) => { + var startWindowDragTimer: any; + const moveHandler = (e: PointerEvent) => { e.preventDefault(); // required or dragging text menu link item ends up dragging the link button as native drag/drop if (dragData instanceof DocumentDragData) { dragData.userDropAction = e.ctrlKey && e.altKey ? "copy" : e.ctrlKey ? "alias" : dragData.defaultDropAction; } - if (e?.shiftKey && dragData.draggedDocuments.length === 1) { - dragData.dropAction = dragData.userDropAction || "same"; - if (dragData.dropAction === "move") { - dragData.removeDocument?.(dragData.draggedDocuments[0]); + if (((e.target as any)?.className === "lm_tabs" || (e.target as any)?.className === "lm_header" || e?.shiftKey) && dragData.draggedDocuments.length === 1) { + if (!startWindowDragTimer) { + startWindowDragTimer = setTimeout(async () => { + startWindowDragTimer = undefined; + dragData.dropAction = dragData.userDropAction || "same"; + AbortDrag(); + await finishDrag?.(new DragCompleteEvent(true, dragData)); + DragManager.StartWindowDrag?.(e, dragData.droppedDocuments, (aborted) => { + if (!aborted && (dragData.dropAction === "move" || dragData.dropAction === "same")) { + dragData.removeDocument?.(dragData.draggedDocuments[0]); + } + }); + }, 500); } - AbortDrag(); - await finishDrag?.(new DragCompleteEvent(true, dragData)); - DragManager.StartWindowDrag?.({ - pageX: e.pageX, - pageY: e.pageY, - preventDefault: emptyFunction, - button: 0 - }, dragData.droppedDocuments); + } else { + clearTimeout(startWindowDragTimer); + startWindowDragTimer = undefined; } const target = document.elementFromPoint(e.x, e.y); @@ -536,6 +542,8 @@ export namespace DragManager { ); }; const upHandler = (e: PointerEvent) => { + clearTimeout(startWindowDragTimer); + startWindowDragTimer = undefined; dispatchDrag(document.elementFromPoint(e.x, e.y) || document.body, e, new DragCompleteEvent(false, dragData), snapDrag(e, xFromLeft, yFromTop, xFromRight, yFromBottom), finishDrag, options, cleanupDrag); }; document.addEventListener("pointermove", moveHandler, true); |