aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Utils.ts4
-rw-r--r--src/client/util/DragManager.ts41
-rw-r--r--src/client/views/MainView.tsx8
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx70
-rw-r--r--src/client/views/nodes/formattedText/DashFieldView.tsx4
-rw-r--r--src/server/authentication/models/current_user_utils.ts6
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