diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Utils.ts | 4 | ||||
-rw-r--r-- | src/client/util/DragManager.ts | 41 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 8 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 70 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/DashFieldView.tsx | 4 | ||||
-rw-r--r-- | src/server/authentication/models/current_user_utils.ts | 6 |
6 files changed, 60 insertions, 73 deletions
diff --git a/src/Utils.ts b/src/Utils.ts index ad12c68a1..23b59ac9d 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -4,7 +4,7 @@ import { Socket, Room } from 'socket.io'; import { Message } from './server/Message'; export namespace Utils { - export const DRAG_THRESHOLD = 4; + export let DRAG_THRESHOLD = 4; export function GenerateGuid(): string { return v4(); @@ -512,7 +512,7 @@ export function setupMoveUpEvents( (target as any)._downY = (target as any)._lastY = e.clientY; const _moveEvent = (e: PointerEvent): void => { - if (Math.abs(e.clientX - (target as any)._downX) > 4 || Math.abs(e.clientY - (target as any)._downY) > 4) { + if (Math.abs(e.clientX - (target as any)._downX) > Utils.DRAG_THRESHOLD || Math.abs(e.clientY - (target as any)._downY) > Utils.DRAG_THRESHOLD) { if (moveEvent(e, [(target as any)._downX, (target as any)._downY], [e.clientX - (target as any)._lastX, e.clientY - (target as any)._lastY])) { document.removeEventListener("pointermove", _moveEvent); diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index c03d9ea1b..c48611eff 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,5 +1,5 @@ import { Doc, Field, DocListCast } from "../../new_fields/Doc"; -import { Cast, ScriptCast, StrCast } from "../../new_fields/Types"; +import { Cast, ScriptCast, StrCast, NumCast } from "../../new_fields/Types"; import { emptyFunction } from "../../Utils"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import * as globalCssVariables from "../views/globalCssVariables.scss"; @@ -305,33 +305,20 @@ export namespace DragManager { } export function snapDrag(e: PointerEvent, xFromLeft: number, yFromTop: number, xFromRight: number, yFromBottom: number) { - let thisX = e.pageX; - let thisY = e.pageY; - const currLeft = e.pageX - xFromLeft; - const currTop = e.pageY - yFromTop; - const currRight = e.pageX + xFromRight; - const currBottom = e.pageY + yFromBottom; - const closestLeft = vertSnapLines.length ? vertSnapLines.reduce((prev, curr) => Math.abs(prev - currLeft) > Math.abs(curr - currLeft) ? curr : prev) : currLeft; - const closestTop = horizSnapLines.length ? horizSnapLines.reduce((prev, curr) => Math.abs(prev - currTop) > Math.abs(curr - currTop) ? curr : prev) : currTop; - const closestRight = vertSnapLines.length ? vertSnapLines.reduce((prev, curr) => Math.abs(prev - currRight) > Math.abs(curr - currRight) ? curr : prev) : currRight; - const closestBottom = horizSnapLines.length ? horizSnapLines.reduce((prev, curr) => Math.abs(prev - currBottom) > Math.abs(curr - currBottom) ? curr : prev) : currBottom; - const distFromClosestLeft = Math.abs(e.pageX - xFromLeft - closestLeft); - const distFromClosestTop = Math.abs(e.pageY - yFromTop - closestTop); - const distFromClosestRight = Math.abs(e.pageX + xFromRight - closestRight); - const distFromClosestBottom = Math.abs(e.pageY + yFromBottom - closestBottom); - if (distFromClosestLeft < 10 && distFromClosestLeft < distFromClosestRight) { - thisX = closestLeft + xFromLeft; - } - else if (distFromClosestRight < 10) { - thisX = closestRight - xFromRight; - } - if (distFromClosestTop < 10 && distFromClosestTop < distFromClosestBottom) { - thisY = closestTop + yFromTop; - } - else if (distFromClosestBottom < 10) { - thisY = closestBottom - yFromBottom; + const snapThreshold = NumCast(Doc.UserDoc()["constants-snapThreshold"], 10); + 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 + const rangePts = [drag - offs[0], drag - offs[1], drag - offs[2]]; // left, mid, right or top, mid, bottom pts to try to snap to snaplines + const closestPts = rangePts.map(pt => snapLines.reduce((nearest, curr) => Math.abs(nearest - pt) > Math.abs(curr - pt) ? curr : nearest)); + const closestDists = rangePts.map((pt, i) => Math.abs(pt - closestPts[i])); + const minIndex = closestDists[0] < closestDists[1] && closestDists[0] < closestDists[2] ? 0 : closestDists[1] < closestDists[2] ? 1 : 2; + return closestDists[minIndex] < snapThreshold ? closestPts[minIndex] + offs[minIndex] : drag; + } + return drag; } - return { thisX, thisY }; + + return { thisX: snapVal([xFromLeft, xFromRight], e.pageX, vertSnapLines), thisY: snapVal([yFromTop, yFromBottom], e.pageY, horizSnapLines) }; } export let docsBeingDragged: Doc[] = []; function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: DragCompleteEvent) => void) { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index e5a8ebcb5..72dfdf75c 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -588,12 +588,12 @@ export class MainView extends React.Component { <RichTextMenu /> <OverlayView /> {// TO VIEW SNAP LINES - /* <div className="snapLines" style={{ position: "absolute", top: 0, left: 0, width: "100%", height: "100%", pointerEvents: "none" }}> + <div className="snapLines" style={{ position: "absolute", top: 0, left: 0, width: "100%", height: "100%", pointerEvents: "none" }}> <svg style={{ width: "100%", height: "100%" }}> - {this._hLines?.map(l => <line x1="0" y1={l} x2="2000" y2={l} stroke="black" />)} - {this._vLines?.map(l => <line y1="0" x1={l} y2="2000" x2={l} stroke="black" />)} + {this._hLines?.map(l => <line x1="0" y1={l} x2="2000" y2={l} stroke="black" opacity={0.3} strokeWidth={0.5} strokeDasharray={"1 1"} />)} + {this._vLines?.map(l => <line y1="0" x1={l} y2="2000" x2={l} stroke="black" opacity={0.3} strokeWidth={0.5} strokeDasharray={"1 1"} />)} </svg> - </div>*/} + </div>} <TimelineMenu /> </div >); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 11d0f298d..763a6c605 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -869,6 +869,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P LibraryPath: this.libraryPath, FreezeDimensions: this.props.freezeChildDimensions, layoutKey: undefined, + setupDragLines: this.setupDragLines, rootSelected: childData ? this.rootSelected : returnFalse, dropAction: StrCast(this.props.Document.childDropAction) as dropActionType, //onClick: undefined, // this.props.onClick, // bcz: check this out -- I don't think we want to inherit click handlers, or we at least need a way to ignore them @@ -1146,37 +1147,36 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P } @action + setupDragLines = () => { + const size = this.props.ScreenToLocalTransform().transformDirection(this.props.PanelWidth(), this.props.PanelHeight()); + const selRect = { left: this.panX() - size[0] / 2, top: this.panY() - size[1] / 2, width: size[0], height: size[1] }; + const docDims = (doc: Doc) => ({ left: NumCast(doc.x), top: NumCast(doc.y), width: NumCast(doc._width), height: NumCast(doc._height) }); + const isDocInView = (doc: Doc, rect: { left: number, top: number, width: number, height: number }) => { + if (this.intersectRect(docDims(doc), rect)) { + snappableDocs.push(doc); + } + } + const snappableDocs: Doc[] = []; // the set of documents in the visible viewport that we will try to snap to; + const otherBounds = { left: this.panX(), top: this.panY(), width: Math.abs(size[0]), height: Math.abs(size[1]) }; + this.getActiveDocuments().filter(doc => !doc.isBackground && doc.z === undefined).map(doc => isDocInView(doc, selRect)); // first see if there are any foreground docs to snap to + !snappableDocs.length && this.getActiveDocuments().filter(doc => doc.z === undefined).map(doc => isDocInView(doc, selRect)); // if not, see if there are background docs to snap to + !snappableDocs.length && this.getActiveDocuments().filter(doc => doc.z !== undefined).map(doc => isDocInView(doc, otherBounds)); // if not, then why not snap to floating docs + + const horizLines: number[] = []; + const vertLines: number[] = []; + snappableDocs.filter(doc => !DragManager.docsBeingDragged.includes(Cast(doc.rootDocument, Doc, null) || doc)).forEach(doc => { + const { left, top, width, height } = docDims(doc); + const topLeftInScreen = this.getTransform().inverse().transformPoint(left, top); + const docSize = this.getTransform().inverse().transformDirection(width, height); + + horizLines.push(topLeftInScreen[1], topLeftInScreen[1] + docSize[1] / 2, topLeftInScreen[1] + docSize[1]); // horiz center line + vertLines.push(topLeftInScreen[0], topLeftInScreen[0] + docSize[0] / 2, topLeftInScreen[0] + docSize[0]);// right line + }); + DragManager.SetSnapLines(horizLines, vertLines); + } onPointerOver = (e: React.PointerEvent) => { if (SelectionManager.GetIsDragging()) { - const size = this.props.ScreenToLocalTransform().transformDirection(this.props.PanelWidth(), this.props.PanelHeight()); - const selRect = { left: this.panX() - size[0] / 2, top: this.panY() - size[1] / 2, width: size[0], height: size[1] }; - const selection: Doc[] = []; - const docDims = (doc: Doc, layoutDoc: Doc) => ({ left: NumCast(doc.x), top: NumCast(doc.y), width: NumCast(layoutDoc._width), height: NumCast(layoutDoc._height) }); - const compareDoc = (doc: Doc, rect: { left: number, top: number, width: number, height: number }) => { - if (this.intersectRect(docDims(doc, Doc.Layout(doc)), rect)) { - selection.push(doc); - } - } - const otherBounds = { left: this.panX(), top: this.panY(), width: Math.abs(size[0]), height: Math.abs(size[1]) }; - this.getActiveDocuments().filter(doc => !doc.isBackground && doc.z === undefined).map(doc => compareDoc(doc, selRect)); // first try foreground docs - !selection.length && this.getActiveDocuments().filter(doc => doc.z === undefined).map(doc => compareDoc(doc, selRect)); // then background docs - !selection.length && this.getActiveDocuments().filter(doc => doc.z !== undefined).map(doc => compareDoc(doc, otherBounds)); // then floating docs - - const horizLines: number[] = []; - const vertLines: number[] = []; - selection.filter(doc => !DragManager.docsBeingDragged.includes(doc)).forEach(doc => { - const { left, top, width, height } = docDims(doc, Doc.Layout(doc)); - const topLeftInScreen = this.getTransform().inverse().transformPoint(left, top); - const docSize = this.getTransform().inverse().transformDirection(width, height); - - horizLines.push(topLeftInScreen[1]); // top line - horizLines.push(topLeftInScreen[1] + docSize[1]); // bottom line - horizLines.push(topLeftInScreen[1] + docSize[1] / 2); // horiz center line - vertLines.push(topLeftInScreen[0]);//left line - vertLines.push(topLeftInScreen[0] + docSize[0]);// right line - vertLines.push(topLeftInScreen[0] + docSize[0] / 2);// vert center line - }); - DragManager.SetSnapLines(horizLines, vertLines); + this.setupDragLines(e); } e.stopPropagation(); } @@ -1273,12 +1273,12 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P }}> </div> {// uncomment to show snap lines - /*<div className="snapLines" style={{ position: "absolute", top: 0, left: 0, width: "100%", height: "100%", pointerEvents: "none" }}> - <svg style={{ width: "100%", height: "100%" }}> - {this._hLines?.map(l => <line x1="0" y1={l} x2="1000" y2={l} stroke="black" />)} - {this._vLines?.map(l => <line y1="0" x1={l} y2="1000" x2={l} stroke="black" />)} - </svg> - </div>*/} + <div className="snapLines" style={{ position: "absolute", top: 0, left: 0, width: "100%", height: "100%", pointerEvents: "none" }}> + <svg style={{ width: "100%", height: "100%" }}> + {this._hLines?.map(l => <line x1="0" y1={l} x2="1000" y2={l} stroke="black" />)} + {this._vLines?.map(l => <line y1="0" x1={l} y2="1000" x2={l} stroke="black" />)} + </svg> + </div>} </div >; } } diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index 422710c3e..1b22ed4cd 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -34,8 +34,6 @@ export class DashFieldView { docid={node.attrs.docid} width={node.attrs.width} height={node.attrs.height} - view={view} - getPos={getPos} tbox={tbox} />, this._fieldWrapper); (this as any).dom = this._fieldWrapper; @@ -49,8 +47,6 @@ export class DashFieldView { interface IDashFieldViewInternal { fieldKey: string; docid: string; - view: any; - getPos: any; tbox: FormattedTextBox; width: number; height: number; diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index e49cc4804..663343f47 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -1,5 +1,6 @@ import { action, computed, observable, reaction } from "mobx"; import * as rp from 'request-promise'; +import { Utils } from "../../../Utils"; import { DocServer } from "../../../client/DocServer"; import { Docs, DocumentOptions } from "../../../client/documents/Documents"; import { UndoManager } from "../../../client/util/UndoManager"; @@ -7,7 +8,7 @@ import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; import { ScriptField, ComputedField } from "../../../new_fields/ScriptField"; -import { Cast, PromiseValue, StrCast } from "../../../new_fields/Types"; +import { Cast, PromiseValue, StrCast, NumCast } from "../../../new_fields/Types"; import { Utils } from "../../../Utils"; import { nullAudio, ImageField } from "../../../new_fields/URLField"; import { DragManager } from "../../../client/util/DragManager"; @@ -628,6 +629,9 @@ export class CurrentUserUtils { new InkingControl(); doc.title = Doc.CurrentUserEmail; doc.activePen = doc; + doc["constants-snapThreshold"] = NumCast(doc["constants-snapThreshold"], 10); // + doc["constants-dragThreshold"] = NumCast(doc["constants-dragThreshold"], 4); // + Utils.DRAG_THRESHOLD = NumCast(doc["constants-dragThreshold"]); this.setupDefaultIconTemplates(doc); // creates a set of icon templates triggered by the document deoration icon this.setupDocTemplates(doc); // sets up the template menu of templates this.setupRightSidebar(doc); // sets up the right sidebar collection for mobile upload documents and sharing |