aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/util/CurrentUserUtils.ts2
-rw-r--r--src/client/util/InteractionUtils.tsx60
-rw-r--r--src/client/util/SettingsManager.tsx2
-rw-r--r--src/client/views/GestureOverlay.tsx59
-rw-r--r--src/client/views/GlobalKeyHandler.ts4
-rw-r--r--src/client/views/InkingStroke.tsx30
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx12
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx2
-rw-r--r--src/client/views/collections/collectionFreeForm/FormatShapePane.tsx72
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx58
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx6
-rw-r--r--src/client/views/linking/LinkEditor.tsx4
-rw-r--r--src/client/views/nodes/PresBox.tsx24
13 files changed, 226 insertions, 109 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 49377a728..b2fb1e33a 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -436,7 +436,7 @@ export class CurrentUserUtils {
{ toolTip: "Drag a audio recorder", title: "Audio", icon: "microphone", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyAudio as Doc, noviceMode: true },
{ toolTip: "Drag a button", title: "Button", icon: "bolt", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyButton as Doc, noviceMode: true },
- { toolTip: "Drag a presentation view", title: "Prezi", icon: "tv", click: 'openOnRight(Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true))', drag: `Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true)`, dragFactory: doc.emptyPresentation as Doc, noviceMode: true },
+ { toolTip: "Drag a presentation view", title: "Present", icon: "tv", click: 'openOnRight(Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true))', drag: `Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true)`, dragFactory: doc.emptyPresentation as Doc, noviceMode: true },
{ toolTip: "Drag a search box", title: "Query", icon: "search", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptySearch as Doc },
{ toolTip: "Drag a scripting box", title: "Script", icon: "terminal", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyScript as Doc },
// { title: "Drag an import folder", title: "Load", icon: "cloud-upload-alt", ignoreClick: true, drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", _width: 400, _height: 400 })' },
diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx
index 04a750f93..ae3b3e064 100644
--- a/src/client/util/InteractionUtils.tsx
+++ b/src/client/util/InteractionUtils.tsx
@@ -91,15 +91,61 @@ export namespace InteractionUtils {
return myTouches;
}
- export function CreatePolyline(points: { X: number, Y: number }[], left: number, top: number,
+ export function CreatePoints(points: { X: number, Y: number }[], left: number, top: number,
color: string, width: number, strokeWidth: number, bezier: string, fill: string, arrowStart: string, arrowEnd: string,
dash: string, scalex: number, scaley: number, shape: string, pevents: string, drawHalo: boolean, nodefs: boolean) {
+ let pts: { X: number; Y: number; }[] = [];
+ if (shape) { //if any of the shape are true
+ pts = makePolygon(shape, points);
+ }
+ else if ((points.length >= 5 && points[3].X === points[4].X) || (points.length === 4)) {
+ for (var i = 0; i < points.length - 3; i += 4) {
+ const array = [[points[i].X, points[i].Y], [points[i + 1].X, points[i + 1].Y], [points[i + 2].X, points[i + 2].Y], [points[i + 3].X, points[i + 3].Y]];
+ for (var t = 0; t < 1; t += 0.01) {
+ const point = beziercurve(t, array);
+ pts.push({ X: point[0], Y: point[1] });
+ }
+ }
+ }
+ else if (points.length > 1 && points[points.length - 1].X === points[0].X && points[points.length - 1].Y === points[0].Y) {
+ //pointer is up (first and last points are the same)
+ const newPoints = points.reduce((p, pts) => { p.push([pts.X, pts.Y]); return p; }, [] as number[][]);
+ newPoints.pop();
+ const bezierCurves = fitCurve(newPoints, parseInt(bezier));
+ for (const curve of bezierCurves) {
+ for (var t = 0; t < 1; t += 0.01) {
+ const point = beziercurve(t, curve);
+ pts.push({ X: point[0], Y: point[1] });
+ }
+ }
+ } else {
+ pts = points.slice();
+ // bcz: Ugh... this is ugly, but shapes apprently have an extra point added that is = (p[0].x,p[0].y+1) as some sort of flag. need to remove it here.
+ if (pts.length > 2 && pts[pts.length - 2].X === pts[0].X && pts[pts.length - 2].Y === pts[0].Y) {
+ pts.pop();
+ }
+ }
+ if (isNaN(scalex)) {
+ scalex = 1;
+ }
+ if (isNaN(scaley)) {
+ scaley = 1;
+ }
+ console.log(pts.length);
+ return pts;
+ }
+
+
+
+ export function CreatePolyline(points: { X: number, Y: number }[], left: number, top: number,
+ color: string, width: number, strokeWidth: number, bezier: string, fill: string, arrowStart: string, arrowEnd: string,
+ dash: string, scalex: number, scaley: number, shape: string, pevents: string, drawHalo: boolean, nodefs: boolean) {
let pts: { X: number; Y: number; }[] = [];
if (shape) { //if any of the shape are true
pts = makePolygon(shape, points);
}
- else if (points.length >= 5 && points[3].X === points[4].X) {
+ else if ((points.length >= 5 && points[3].X === points[4].X) || (points.length === 4)) {
for (var i = 0; i < points.length - 3; i += 4) {
const array = [[points[i].X, points[i].Y], [points[i + 1].X, points[i + 1].Y], [points[i + 2].X, points[i + 2].Y], [points[i + 3].X, points[i + 3].Y]];
for (var t = 0; t < 1; t += 0.01) {
@@ -139,6 +185,15 @@ export namespace InteractionUtils {
const dashArray = String(Number(width) * Number(dash));
const defGuid = Utils.GenerateGuid();
const arrowDim = Math.max(0.5, 8 / Math.log(Math.max(2, strokeWidth)));
+
+ const addables = pts.map((pts, i) =>
+ <svg height="10" width="10">
+ <circle cx={(pts.X - left - width / 2) * scalex + width / 2} cy={(pts.Y - top - width / 2) * scaley + width / 2} r={strokeWidth / 2} stroke="black" stroke-width={1} fill="blue"
+ onDoubleClick={(e) => { console.log(i); }} pointerEvents="all" cursor="all-scroll"
+ />
+ </svg>);
+
+
return (<svg fill={color}> {/* setting the svg fill sets the arrowStart fill */}
{nodefs ? (null) : <defs>
{arrowStart !== "dot" && arrowEnd !== "dot" ? (null) : <marker id={`dot${defGuid}`} orient="auto" overflow="visible">
@@ -167,6 +222,7 @@ export namespace InteractionUtils {
markerStart={`url(#${arrowStart + "Start" + defGuid})`}
markerEnd={`url(#${arrowEnd + "End" + defGuid})`}
/>
+ {/* {addables} */}
</svg>);
}
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index 513cece40..e3b91925a 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -146,7 +146,7 @@ export default class SettingsManager extends React.Component<{}> {
@computed get accountsContent() {
return <div className="accounts-content">
<button onClick={this.googleAuthorize} value="data">Link to Google</button>
- <button onClick={GroupManager.Instance?.open}>Manage groups</button>
+ <button onClick={() => GroupManager.Instance?.open()}>Manage groups</button>
</div>;
}
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 30df7cf9a..81bb542dd 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -733,19 +733,8 @@ export default class GestureOverlay extends Touchable {
this._points.push({ X: left, Y: top });
this._points.push({ X: left, Y: top });
- // this._points.push({ X: left, Y: top });
-
- // this._points.push({ X: left, Y: top });
- // this._points.push({ X: left, Y: top });
-
- // this._points.push({ X: left, Y: top - 1 });
break;
case "triangle":
- // this._points.push({ X: left, Y: bottom });
- // this._points.push({ X: right, Y: bottom });
- // this._points.push({ X: (right + left) / 2, Y: top });
- // this._points.push({ X: left, Y: bottom });
- // this._points.push({ X: left, Y: bottom - 1 });
this._points.push({ X: left, Y: bottom });
this._points.push({ X: left, Y: bottom });
@@ -779,60 +768,12 @@ export default class GestureOverlay extends Touchable {
}
this._points.push({ X: Math.sqrt(Math.pow(radius, 2) - (Math.pow((top - centerY), 2))) + centerX, Y: top });
this._points.push({ X: Math.sqrt(Math.pow(radius, 2) - (Math.pow((top - centerY), 2))) + centerX, Y: top - 1 });
- // this._points.push({ X: centerX, Y: top });
- // this._points.push({ X: centerX + radius / 2, Y: top });
-
- // this._points.push({ X: right, Y: top + radius / 2 });
- // this._points.push({ X: right, Y: top + radius });
- // this._points.push({ X: right, Y: top + radius });
- // this._points.push({ X: right, Y: bottom - radius / 2 });
-
- // this._points.push({ X: right - radius / 2, Y: bottom });
- // this._points.push({ X: right - radius, Y: bottom });
- // this._points.push({ X: right - radius, Y: bottom });
- // this._points.push({ X: left + radius / 2, Y: bottom });
-
- // this._points.push({ X: left, Y: bottom - radius / 2 });
- // this._points.push({ X: left, Y: bottom - radius });
- // this._points.push({ X: left, Y: bottom - radius });
- // this._points.push({ X: left, Y: top + radius / 2 });
-
- // this._points.push({ X: left + radius / 2, Y: top });
- // this._points.push({ X: left + radius, Y: top });
-
-
-
-
-
-
break;
case "line":
- // const firstx = this._points[0].X;
- // const firsty = this._points[0].Y;
- // const lastx = this._points[this._points.length - 1].X;
- // const lasty = this._points[this._points.length - 1].Y;
- // const fourth = (lastx - firstx) / 4;
- // const m = (lasty - firsty) / (lastx - firstx);
- // const b = firsty - m * firstx;
this._points.push({ X: firstx, Y: firsty });
this._points.push({ X: firstx, Y: firsty });
- this._points.push({ X: firstx + fourth, Y: m * (firstx + fourth) + b });
- this._points.push({ X: firstx + fourth, Y: m * (firstx + fourth) + b });
- this._points.push({ X: firstx + fourth, Y: m * (firstx + fourth) + b });
- this._points.push({ X: firstx + fourth, Y: m * (firstx + fourth) + b });
-
- this._points.push({ X: firstx + 2 * fourth, Y: m * (firstx + 2 * fourth) + b });
- this._points.push({ X: firstx + 2 * fourth, Y: m * (firstx + 2 * fourth) + b });
- this._points.push({ X: firstx + 2 * fourth, Y: m * (firstx + 2 * fourth) + b });
- this._points.push({ X: firstx + 2 * fourth, Y: m * (firstx + 2 * fourth) + b });
-
- this._points.push({ X: firstx + 3 * fourth, Y: m * (firstx + 3 * fourth) + b });
- this._points.push({ X: firstx + 3 * fourth, Y: m * (firstx + 3 * fourth) + b });
- this._points.push({ X: firstx + 3 * fourth, Y: m * (firstx + 3 * fourth) + b });
- this._points.push({ X: firstx + 3 * fourth, Y: m * (firstx + 3 * fourth) + b });
-
this._points.push({ X: firstx + 4 * fourth, Y: m * (firstx + 4 * fourth) + b });
this._points.push({ X: firstx + 4 * fourth, Y: m * (firstx + 4 * fourth) + b });
break;
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 2b31a8612..c97882f06 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -108,7 +108,9 @@ export default class KeyManager {
GoogleAuthenticationManager.Instance.cancel();
SharingManager.Instance.close();
GroupManager.Instance.close();
- CollectionFreeFormViewChrome.Instance.clearKeep();
+ CollectionFreeFormViewChrome.Instance?.clearKeep();
+ window.getSelection()?.empty();
+ document.body.focus();
break;
case "delete":
case "backspace":
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 4a77728b6..e3390426b 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -52,8 +52,8 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
FormatShapePane.Instance.Pinned = true;
}
- private _prevX = 0;
- private _prevY = 0;
+ public _prevX = 0;
+ public _prevY = 0;
private _controlNum = 0;
@action
onControlDown = (e: React.PointerEvent, i: number): void => {
@@ -67,6 +67,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
@action
changeCurrPoint = (i: number) => {
FormatShapePane.Instance._currPoint = i;
+ document.addEventListener("keydown", this.delPts, true);
}
@action
@@ -86,6 +87,13 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
this._controlUndo?.end();
this._controlUndo = undefined;
}
+ @action
+ delPts = (e: KeyboardEvent | React.PointerEvent | undefined) => {
+ if (e instanceof KeyboardEvent ? e.key === "-" : true) {
+ FormatShapePane.Instance.deletePoints();
+ }
+ }
+
public static MaskDim = 50000;
render() {
@@ -115,6 +123,12 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "transparent"),
"none", "none", "0", scaleX, scaleY, "", this.props.active() ? "visiblepainted" : "none", false, true);
+ //points for adding
+ const apoints = InteractionUtils.CreatePoints(data, left, top, strokeColor, strokeWidth, strokeWidth,
+ StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "transparent"),
+ StrCast(this.layoutDoc.strokeStartMarker), StrCast(this.layoutDoc.strokeEndMarker),
+ StrCast(this.layoutDoc.strokeDash), scaleX, scaleY, "", "none", this.props.isSelected() && strokeWidth <= 5, false);
+
const controlPoints: { X: number, Y: number, I: number }[] = [];
const handlePoints: { X: number, Y: number, I: number, dot1: number, dot2: number }[] = [];
const handleLine: { X1: number, Y1: number, X2: number, Y2: number, X3: number, Y3: number, dot1: number, dot2: number }[] = [];
@@ -146,11 +160,20 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
// }
const dotsize = String(Math.max(width * scaleX, height * scaleY) / 40);
+ const addpoints = apoints.map((pts, i) =>
+
+ <svg height="10" width="10">
+ <circle cx={(pts.X - left - strokeWidth / 2) * scaleX + strokeWidth / 2} cy={(pts.Y - top - strokeWidth / 2) * scaleY + strokeWidth / 2} r={dotsize} stroke="invisible" stroke-width={String(Number(dotsize) / 2)} fill="invisible"
+ onPointerDown={(e) => { FormatShapePane.Instance.addPoints(pts.X, pts.Y, apoints, i, controlPoints); }} pointerEvents="all" cursor="all-scroll"
+ />
+ </svg>);
+
const controls = controlPoints.map((pts, i) =>
<svg height="10" width="10">
<circle cx={(pts.X - left - strokeWidth / 2) * scaleX + strokeWidth / 2} cy={(pts.Y - top - strokeWidth / 2) * scaleY + strokeWidth / 2} r={dotsize} stroke="black" stroke-width={String(Number(dotsize) / 2)} fill="red"
- onPointerDown={(e) => { this.changeCurrPoint(pts.I); this.onControlDown(e, pts.I); }} pointerEvents="all" cursor="all-scroll" />
+ onPointerDown={(e) => { this.changeCurrPoint(pts.I); this.onControlDown(e, pts.I); }} pointerEvents="all" cursor="all-scroll"
+ />
</svg>);
const handles = handlePoints.map((pts, i) =>
@@ -193,6 +216,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
</defs>
{hpoints}
{points}
+ {FormatShapePane.Instance._controlBtn && this.props.isSelected() ? addpoints : ""}
{FormatShapePane.Instance._controlBtn && this.props.isSelected() ? controls : ""}
{FormatShapePane.Instance._controlBtn && this.props.isSelected() ? handles : ""}
{FormatShapePane.Instance._controlBtn && this.props.isSelected() ? handleLines : ""}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 7e096fa37..3691e844f 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -513,7 +513,11 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
const doc = await DocServer.GetRefField(tab.contentItem.config.props.documentId) as Doc;
if (doc instanceof Doc) {
- tab.titleElement[0].onclick = (e: any) => tab.titleElement[0].focus();
+ tab.titleElement[0].onclick = (e: any) => {
+ if (Date.now() - tab.titleElement[0].lastClick < 1000) tab.titleElement[0].select();
+ tab.titleElement[0].lastClick = Date.now();
+ tab.titleElement[0].focus();
+ };
tab.titleElement[0].onchange = (e: any) => {
tab.titleElement[0].size = e.currentTarget.value.length + 1;
Doc.GetProto(doc).title = e.currentTarget.value, true;
@@ -691,8 +695,8 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
return (this.props as any).glContainer.parent.parent;
}
get _tab(): any {
- const tab = (this.props as any).glContainer.tab.element[0] as HTMLElement;
- return tab.getElementsByClassName("lm_title")?.[0];
+ const tab = (this.props as any).glContainer.tab?.element[0] as HTMLElement;
+ return tab?.getElementsByClassName("lm_title")?.[0];
}
constructor(props: any) {
super(props);
@@ -757,7 +761,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
this._tabReaction = reaction(() => ({ views: SelectionManager.SelectedDocuments(), color: StrCast(this._document?._backgroundColor, "white") }),
(data) => {
const selected = data.views.some(v => Doc.AreProtosEqual(v.props.Document, this._document));
- this._tab.style.backgroundColor = selected ? data.color : "";
+ this._tab && (this._tab.style.backgroundColor = selected ? data.color : "");
}
);
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index ef4b7b9d2..2b8e949b1 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1257,7 +1257,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
!this.props.isAnnotationOverlay && !Doc.UserDoc().noviceMode &&
optionItems.push({ description: (this.showTimeline ? "Close" : "Open") + " Animation Timeline", event: action(() => this.showTimeline = !this.showTimeline), icon: faEye });
this.props.ContainingCollectionView &&
- optionItems.push({ description: "Promote Collection", event: this.promoteCollection, icon: "table" });
+ optionItems.push({ description: "Undo Collection", event: this.promoteCollection, icon: "table" });
optionItems.push({ description: this.layoutDoc._lockedTransform ? "Unlock Transform" : "Lock Transform", event: this.toggleLockTransform, icon: this.layoutDoc._lockedTransform ? "unlock" : "lock" });
optionItems.push({ description: "Use Background Color as Default", event: () => Cast(Doc.UserDoc().emptyCollection, Doc, null)._backgroundColor = StrCast(this.layoutDoc._backgroundColor), icon: "palette" });
if (!Doc.UserDoc().noviceMode) {
diff --git a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
index 6263be261..1ffa2fbed 100644
--- a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
+++ b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
@@ -163,6 +163,78 @@ export default class FormatShapePane extends AntimodeMenu {
@undoBatch
@action
+ addPoints = (x: number, y: number, pts: { X: number, Y: number }[], index: number, control: { X: number, Y: number }[]) => {
+ this.selectedInk?.forEach(action(inkView => {
+ if (this.selectedInk?.length === 1) {
+ const doc = Document(inkView.rootDoc);
+ if (doc.type === DocumentType.INK) {
+ const ink = Cast(doc.data, InkField)?.inkData;
+ if (ink) {
+ const newPoints: { X: number, Y: number }[] = [];
+ var counter = 0;
+ for (var k = 0; k < index; k++) {
+ control.forEach(pt => (pts[k].X === pt.X && pts[k].Y === pt.Y) && counter++);
+ }
+ //decide where to put the new coordinate
+ const spNum = Math.floor(counter / 2) * 4 + 2;
+
+ for (var i = 0; i < spNum; i++) {
+ newPoints.push({ X: ink[i].X, Y: ink[i].Y });
+ }
+ for (var j = 0; j < 4; j++) {
+ newPoints.push({ X: x, Y: y });
+
+ }
+ for (var i = spNum; i < ink.length; i++) {
+ newPoints.push({ X: ink[i].X, Y: ink[i].Y });
+ }
+ this._currPoint = -1;
+ doc.data = new InkField(newPoints);
+ }
+ }
+ }
+ }));
+ }
+
+ @undoBatch
+ @action
+ deletePoints = () => {
+ this.selectedInk?.forEach(action(inkView => {
+ if (this.selectedInk?.length === 1 && this._currPoint !== -1) {
+ const doc = Document(inkView.rootDoc);
+ if (doc.type === DocumentType.INK) {
+ const ink = Cast(doc.data, InkField)?.inkData;
+ if (ink && ink.length > 4) {
+ const newPoints: { X: number, Y: number }[] = [];
+
+ console.log(ink.length, this._currPoint, Math.floor((this._currPoint + 2) / 4));
+
+ const toRemove = Math.floor(((this._currPoint + 2) / 4));
+ for (var i = 0; i < ink.length; i++) {
+ if (Math.floor((i + 2) / 4) !== toRemove) {
+ console.log(i, toRemove);
+ newPoints.push({ X: ink[i].X, Y: ink[i].Y });
+ }
+ }
+ this._currPoint = -1;
+ doc.data = new InkField(newPoints);
+ if (newPoints.length === 4) {
+ const newerPoints: { X: number, Y: number }[] = [];
+ newerPoints.push({ X: newPoints[0].X, Y: newPoints[0].Y });
+ newerPoints.push({ X: newPoints[0].X, Y: newPoints[0].Y });
+ newerPoints.push({ X: newPoints[3].X, Y: newPoints[3].Y });
+ newerPoints.push({ X: newPoints[3].X, Y: newPoints[3].Y });
+ doc.data = new InkField(newerPoints);
+
+ }
+ }
+ }
+ }
+ }));
+ }
+
+ @undoBatch
+ @action
rotate = (angle: number) => {
const _centerPoints: { X: number, Y: number }[] = [];
SelectionManager.SelectedDocuments().forEach(action(inkView => {
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
index db4b674b5..f1df7998b 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
@@ -3,6 +3,8 @@ import AntimodeMenu from "../../AntimodeMenu";
import { observer } from "mobx-react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { unimplementedFunction } from "../../../../Utils";
+import { undoBatch } from "../../../util/UndoManager";
+import { Tooltip } from "@material-ui/core";
@observer
export default class MarqueeOptionsMenu extends AntimodeMenu {
@@ -23,34 +25,34 @@ export default class MarqueeOptionsMenu extends AntimodeMenu {
render() {
const buttons = [
- <button
- className="antimodeMenu-button"
- title="Create a Collection"
- key="group"
- onPointerDown={this.createCollection}>
- <FontAwesomeIcon icon="object-group" size="lg" />
- </button>,
- <button
- className="antimodeMenu-button"
- title="Summarize Documents"
- key="summarize"
- onPointerDown={this.summarize}>
- <FontAwesomeIcon icon="compress-arrows-alt" size="lg" />
- </button>,
- <button
- className="antimodeMenu-button"
- title="Delete Documents"
- key="delete"
- onPointerDown={this.delete}>
- <FontAwesomeIcon icon="trash-alt" size="lg" />
- </button>,
- <button
- className="antimodeMenu-button"
- title="Change to Text"
- key="inkToText"
- onPointerDown={this.inkToText}>
- <FontAwesomeIcon icon="font" size="lg" />
- </button>,
+ <Tooltip key="group" title={<><div className="dash-tooltip">Create a Collection</div></>} placement="bottom">
+ <button
+ className="antimodeMenu-button"
+ onPointerDown={this.createCollection}>
+ <FontAwesomeIcon icon="object-group" size="lg" />
+ </button>
+ </Tooltip>,
+ <Tooltip key="summarize" title={<><div className="dash-tooltip">Summarize Documents</div></>} placement="bottom">
+ <button
+ className="antimodeMenu-button"
+ onPointerDown={this.summarize}>
+ <FontAwesomeIcon icon="compress-arrows-alt" size="lg" />
+ </button>
+ </Tooltip>,
+ <Tooltip key="delete" title={<><div className="dash-tooltip">Delete Documents</div></>} placement="bottom">
+ <button
+ className="antimodeMenu-button"
+ onPointerDown={this.delete}>
+ <FontAwesomeIcon icon="trash-alt" size="lg" />
+ </button>
+ </Tooltip>,
+ <Tooltip key="inkToText" title={<><div className="dash-tooltip">Change to Text</div></>} placement="bottom">
+ <button
+ className="antimodeMenu-button"
+ onPointerDown={this.inkToText}>
+ <FontAwesomeIcon icon="font" size="lg" />
+ </button>
+ </Tooltip>,
];
return this.getElement(buttons);
}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index a23f03e2a..2f9c0ca04 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -383,7 +383,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
this.hideMarquee();
}
- @action
+ @undoBatch @action
collection = (e: KeyboardEvent | React.PointerEvent | undefined) => {
const bounds = this.Bounds;
const selected = this.marqueeSelect(false);
@@ -408,7 +408,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
this.hideMarquee();
}
- @action
+ @undoBatch @action
syntaxHighlight = (e: KeyboardEvent | React.PointerEvent | undefined) => {
const selected = this.marqueeSelect(false);
if (e instanceof KeyboardEvent ? e.key === "i" : true) {
@@ -484,7 +484,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
}
}
- @action
+ @undoBatch @action
summary = (e: KeyboardEvent | React.PointerEvent | undefined) => {
const bounds = this.Bounds;
const selected = this.marqueeSelect(false);
diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx
index 3ef391a5d..c9e39cf7b 100644
--- a/src/client/views/linking/LinkEditor.tsx
+++ b/src/client/views/linking/LinkEditor.tsx
@@ -359,7 +359,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
changeFollowBehavior = action((follow: string) => {
this.openDropdown = false;
Doc.GetProto(this.props.linkDoc).followLinkLocation = follow;
- })
+ });
@computed
get followingDropdown() {
@@ -382,7 +382,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
</div>
<div className="linkEditor-followingDropdown-option"
onPointerDown={() => this.changeFollowBehavior("onRight")}>
- Always open in right tab
+ Always open in new pane on right
</div>
<div className="linkEditor-followingDropdown-option"
onPointerDown={() => this.changeFollowBehavior("inTab")}>
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index b7af4683e..849fc4076 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -83,6 +83,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
}
@computed get isPres(): boolean {
if (this.selectedDoc?.type === DocumentType.PRES) {
+ document.removeEventListener("keydown", this.keyEvents, true);
document.addEventListener("keydown", this.keyEvents, true);
return true;
} else {
@@ -91,6 +92,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
}
}
@computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
+ componentWillUnmount() {
+ document.removeEventListener("keydown", this.keyEvents, true);
+ }
componentDidMount() {
this.rootDoc.presBox = this.rootDoc;
@@ -517,29 +521,41 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
// Key for when the presentaiton is active (according to Selection Manager)
@action
keyEvents = (e: KeyboardEvent) => {
- e.stopPropagation();
- e.preventDefault();
-
+ let handled = false;
+ const anchorNode = document.activeElement as HTMLDivElement;
+ if (anchorNode && anchorNode.className?.includes("lm_title")) return;
if (e.keyCode === 27) { // Escape key
if (this.layoutDoc.presStatus === "edit") this._selectedArray = [];
else this.layoutDoc.presStatus = "edit";
+ handled = true;
} if ((e.metaKey || e.altKey) && e.keyCode === 65) { // Ctrl-A to select all
- if (this.layoutDoc.presStatus === "edit") this._selectedArray = this.childDocs;
+ if (this.layoutDoc.presStatus === "edit") {
+ this._selectedArray = this.childDocs;
+ handled = true;
+ }
} if (e.keyCode === 37 || e.keyCode === 38) { // left(37) / a(65) / up(38) to go back
this.back();
+ handled = true;
} if (e.keyCode === 39 || e.keyCode === 40) { // right (39) / d(68) / down(40) to go to next
this.next();
+ handled = true;
} if (e.keyCode === 32) { // spacebar to 'present' or autoplay
if (this.layoutDoc.presStatus !== "edit") this.startAutoPres(0);
else this.layoutDoc.presStatus = "manual";
+ handled = true;
}
if (e.keyCode === 8) { // delete selected items
if (this.layoutDoc.presStatus === "edit") {
this._selectedArray.forEach((doc, i) => {
this.removeDocument(doc);
});
+ handled = true;
}
}
+ if (handled) {
+ e.stopPropagation();
+ e.preventDefault();
+ }
}
/**