aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes')
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx41
-rw-r--r--src/client/views/nodes/ColorBox.tsx49
-rw-r--r--src/client/views/nodes/ComparisonBox.scss16
-rw-r--r--src/client/views/nodes/ComparisonBox.tsx19
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx4
-rw-r--r--src/client/views/nodes/DocumentView.tsx42
-rw-r--r--src/client/views/nodes/ImageBox.tsx2
-rw-r--r--src/client/views/nodes/KeyValuePair.tsx4
-rw-r--r--src/client/views/nodes/PDFBox.tsx2
-rw-r--r--src/client/views/nodes/PresBox.tsx16
-rw-r--r--src/client/views/nodes/ScreenshotBox.tsx12
-rw-r--r--src/client/views/nodes/VideoBox.tsx7
-rw-r--r--src/client/views/nodes/WebBox.tsx25
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.scss11
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx18
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx2
-rw-r--r--src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts18
17 files changed, 179 insertions, 109 deletions
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index a4120f958..910aa744d 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -69,19 +69,24 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
}
public static getValues(doc: Doc, time: number) {
+ const timecode = Math.round(time);
return ({
- x: Cast(doc["x-indexed"], listSpec("number"), []).reduce((p, x, i) => (i <= time && x !== undefined) || p === undefined ? x : p, undefined as any as number),
- y: Cast(doc["y-indexed"], listSpec("number"), []).reduce((p, y, i) => (i <= time && y !== undefined) || p === undefined ? y : p, undefined as any as number),
- opacity: Cast(doc["opacity-indexed"], listSpec("number"), []).reduce((p, o, i) => i <= time || p === undefined ? o : p, undefined as any as number),
+ x: Cast(doc["x-indexed"], listSpec("number"), []).reduce((p, x, i) => (i <= timecode && x !== undefined) || p === undefined ? x : p, undefined as any as number),
+ y: Cast(doc["y-indexed"], listSpec("number"), []).reduce((p, y, i) => (i <= timecode && y !== undefined) || p === undefined ? y : p, undefined as any as number),
+ opacity: Cast(doc["opacity-indexed"], listSpec("number"), []).reduce((p, o, i) => i <= timecode || p === undefined ? o : p, undefined as any as number),
});
}
- public static setValues(timecode: number, d: Doc, x?: number, y?: number, opacity?: number) {
+ public static setValues(time: number, d: Doc, x?: number, y?: number, opacity?: number) {
+ const timecode = Math.round(time);
+ Cast(d["x-indexed"], listSpec("number"), [])[Math.max(0, timecode - 1)] = x as any as number;
+ Cast(d["y-indexed"], listSpec("number"), [])[Math.max(0, timecode - 1)] = y as any as number;
Cast(d["x-indexed"], listSpec("number"), [])[timecode] = x as any as number;
- Cast(d["y-indexed"], listSpec("number"), null)[timecode] = y as any as number;
+ Cast(d["y-indexed"], listSpec("number"), [])[timecode] = y as any as number;
Cast(d["opacity-indexed"], listSpec("number"), null)[timecode] = opacity as any as number;
}
- public static updateKeyframe(docs: Doc[], timecode: number) {
+ public static updateKeyframe(docs: Doc[], time: number) {
+ const timecode = Math.round(time);
docs.forEach(doc => {
const xindexed = Cast(doc['x-indexed'], listSpec("number"), null);
const yindexed = Cast(doc['y-indexed'], listSpec("number"), null);
@@ -91,27 +96,30 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
opacityindexed?.length <= timecode + 1 && opacityindexed.push(undefined as any as number);
doc.transition = "all 1s";
});
- setTimeout(() => docs.forEach(doc => doc.transition = undefined), 1010);
+ setTimeout(() => docs.forEach(doc => doc.transition = "inherit"), 1010);
}
public static gotoKeyframe(docs: Doc[]) {
docs.forEach(doc => doc.transition = "all 1s");
- setTimeout(() => docs.forEach(doc => doc.transition = undefined), 1010);
+ setTimeout(() => docs.forEach(doc => doc.transition = "inherit"), 1010);
}
- public static setupKeyframes(docs: Doc[], timecode: number, collection: Doc) {
+ public static setupKeyframes(docs: Doc[], timecode: number, progressivize: boolean = false) {
docs.forEach((doc, i) => {
+ const curTimecode = progressivize ? i : timecode;
const xlist = new List<number>(numberRange(timecode + 1).map(i => undefined) as any as number[]);
const ylist = new List<number>(numberRange(timecode + 1).map(i => undefined) as any as number[]);
- xlist[Math.max(i - 1)] = xlist[timecode + 1] = NumCast(doc.x);
- ylist[Math.max(i - 1)] = ylist[timecode + 1] = NumCast(doc.y);
+ const olist = new List<number>(numberRange(timecode + 1).map(t => progressivize && t < i ? 0 : 1));
+ xlist[Math.max(curTimecode - 1, 0)] = xlist[curTimecode] = NumCast(doc.x);
+ ylist[Math.max(curTimecode - 1, 0)] = ylist[curTimecode] = NumCast(doc.y);
doc["x-indexed"] = xlist;
doc["y-indexed"] = ylist;
- doc["opacity-indexed"] = new List<number>(numberRange(timecode).map(i => 1));
- doc.displayTimecode = ComputedField.MakeFunction("collection ? collection.currentTimecode : 0", {}, { collection });
- doc.x = ComputedField.MakeInterpolated("x", "displayTimecode");
- doc.y = ComputedField.MakeInterpolated("y", "displayTimecode");
- doc.opacity = ComputedField.MakeInterpolated("opacity", "displayTimecode");
+ doc["opacity-indexed"] = olist;
+ doc.activeFrame = ComputedField.MakeFunction("self.context ? (self.context.currentFrame||0) : 0");
+ doc.x = ComputedField.MakeInterpolated("x", "activeFrame");
+ doc.y = ComputedField.MakeInterpolated("y", "activeFrame");
+ doc.opacity = ComputedField.MakeInterpolated("opacity", "activeFrame");
+ doc.transition = "inherit";
});
}
@@ -146,6 +154,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
width: this.width,
height: this.height,
zIndex: this.ZInd,
+ mixBlendMode: StrCast(this.layoutDoc.mixBlendMode) as any,
display: this.ZInd === -99 ? "none" : undefined,
pointerEvents: this.props.Document.isBackground || this.Opacity === 0 ? "none" : this.props.pointerEvents ? "all" : undefined
}} >
diff --git a/src/client/views/nodes/ColorBox.tsx b/src/client/views/nodes/ColorBox.tsx
index 6d53915ea..0d6258cf3 100644
--- a/src/client/views/nodes/ColorBox.tsx
+++ b/src/client/views/nodes/ColorBox.tsx
@@ -1,15 +1,20 @@
import React = require("react");
+import { action } from "mobx";
import { observer } from "mobx-react";
-import { SketchPicker } from 'react-color';
+import { ColorState, SketchPicker } from 'react-color';
+import { Doc } from "../../../fields/Doc";
+import { Utils } from "../../../Utils";
import { documentSchema } from "../../../fields/documentSchemas";
+import { InkTool } from "../../../fields/InkField";
import { makeInterface } from "../../../fields/Schema";
import { StrCast } from "../../../fields/Types";
-import { CurrentUserUtils } from "../../util/CurrentUserUtils";
import { SelectionManager } from "../../util/SelectionManager";
+import { undoBatch } from "../../util/UndoManager";
import { ViewBoxBaseComponent } from "../DocComponent";
-import { InkingControl } from "../InkingControl";
+import { ActiveInkPen, ActiveInkWidth, ActiveInkBezierApprox, SetActiveInkColor, SetActiveInkWidth, SetActiveBezierApprox } from "../InkingStroke";
import "./ColorBox.scss";
import { FieldView, FieldViewProps } from './FieldView';
+import { FormattedTextBox } from "./formattedText/FormattedTextBox";
type ColorDocument = makeInterface<[typeof documentSchema]>;
const ColorDocument = makeInterface(documentSchema);
@@ -18,18 +23,48 @@ const ColorDocument = makeInterface(documentSchema);
export class ColorBox extends ViewBoxBaseComponent<FieldViewProps, ColorDocument>(ColorDocument) {
public static LayoutString(fieldKey: string) { return FieldView.LayoutString(ColorBox, fieldKey); }
+ @undoBatch
+ @action
+ static switchColor(color: ColorState) {
+ Doc.UserDoc().backgroundColor = Utils.colorString(color);
+ SetActiveInkColor(color.hex);
+
+ if (Doc.GetSelectedTool() === InkTool.None) {
+ const selected = SelectionManager.SelectedDocuments();
+ selected.map(view => {
+ const targetDoc = view.props.Document.dragFactory instanceof Doc ? view.props.Document.dragFactory :
+ view.props.Document.layout instanceof Doc ? view.props.Document.layout :
+ view.props.Document.isTemplateForField ? view.props.Document : Doc.GetProto(view.props.Document);
+ if (targetDoc) {
+ if (StrCast(Doc.Layout(view.props.Document).layout).indexOf("FormattedTextBox") !== -1 && FormattedTextBox.HadSelection) {
+ Doc.Layout(view.props.Document).color = Doc.UserDoc().bacgroundColor;
+ } else {
+ Doc.Layout(view.props.Document)._backgroundColor = Doc.UserDoc().backgroundColor; // '_backgroundColor' is template specific. 'backgroundColor' would apply to all templates, but has no UI at the moment
+ }
+ }
+ });
+ }
+ }
+
+ constructor(props: any) {
+ super(props);
+ }
render() {
const selDoc = SelectionManager.SelectedDocuments()?.[0]?.rootDoc;
return <div className={`colorBox-container${this.active() ? "-interactive" : ""}`}
onPointerDown={e => e.button === 0 && !e.ctrlKey && e.stopPropagation()}
style={{ transform: `scale(${this.props.ContentScaling()})`, width: `${100 / this.props.ContentScaling()}%`, height: `${100 / this.props.ContentScaling()}%` }} >
- <SketchPicker onChange={InkingControl.Instance.switchColor} presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent']}
- color={StrCast(CurrentUserUtils.ActivePen ? CurrentUserUtils.ActivePen.backgroundColor : undefined,
+ <SketchPicker onChange={ColorBox.switchColor} presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent']}
+ color={StrCast(ActiveInkPen()?.backgroundColor,
StrCast(selDoc?._backgroundColor, StrCast(selDoc?.backgroundColor, "black")))} />
<div style={{ display: "grid", gridTemplateColumns: "20% 80%", paddingTop: "10px" }}>
- <div>{InkingControl.Instance.selectedWidth ?? 2}</div>
- <input type="range" value={InkingControl.Instance.selectedWidth ?? 2} defaultValue={2} min={1} max={100} onChange={(e: React.ChangeEvent<HTMLInputElement>) => InkingControl.Instance.switchWidth(e.target.value)} />
+ <div> {ActiveInkWidth() ?? 2}</div>
+ <input type="range" value={ActiveInkWidth() ?? 2} defaultValue={2} min={1} max={100} onChange={(e: React.ChangeEvent<HTMLInputElement>) => SetActiveInkWidth(e.target.value)} />
+ <div> {ActiveInkBezierApprox() ?? 2}</div>
+ <input type="range" value={ActiveInkBezierApprox() ?? 2} defaultValue={2} min={0} max={300} onChange={(e: React.ChangeEvent<HTMLInputElement>) => SetActiveBezierApprox(e.target.value)} />
+ <br />
+ <br />
</div>
</div>;
}
diff --git a/src/client/views/nodes/ComparisonBox.scss b/src/client/views/nodes/ComparisonBox.scss
index 7849c9976..810a824cf 100644
--- a/src/client/views/nodes/ComparisonBox.scss
+++ b/src/client/views/nodes/ComparisonBox.scss
@@ -1,4 +1,5 @@
-.comparisonBox-interactive, .comparisonBox {
+.comparisonBox-interactive,
+.comparisonBox {
border-radius: inherit;
width: 100%;
height: 100%;
@@ -19,13 +20,13 @@
}
}
- .slide-bar {
+ .slide-bar {
position: absolute;
height: 100%;
width: 3px;
display: inline-block;
background: white;
- cursor: ew-resize;
+
.slide-handle {
position: absolute;
display: none;
@@ -33,7 +34,9 @@
width: 30px;
bottom: 0px;
left: -10.5px;
- .left-handle, .right-handle{
+
+ .left-handle,
+ .right-handle {
width: 15px;
}
}
@@ -77,10 +80,13 @@
}
}
}
+
.comparisonBox-interactive {
pointer-events: unset;
+ cursor: ew-resize;
+
.slide-bar {
- .slide-handle {
+ .slide-handle {
display: flex;
}
}
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index 77e07ec0c..cce60628d 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -1,7 +1,7 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable, runInAction, Lambda, IReactionDisposer } from 'mobx';
+import { action, observable } from 'mobx';
import { observer } from "mobx-react";
-import { Doc, Opt } from '../../../fields/Doc';
+import { Doc } from '../../../fields/Doc';
import { documentSchema } from '../../../fields/documentSchemas';
import { createSchema, makeInterface } from '../../../fields/Schema';
import { NumCast, Cast, StrCast } from '../../../fields/Types';
@@ -32,13 +32,14 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps, C
protected createDropTarget = (ele: HTMLDivElement | null, fieldKey: string, disposerId: number) => {
this._disposers[disposerId]?.();
if (ele) {
+ // create disposers identified by disposerId to remove drag & drop listeners
this._disposers[disposerId] = DragManager.MakeDropTarget(ele, (e, dropEvent) => this.dropHandler(e, dropEvent, fieldKey), this.layoutDoc);
}
}
@undoBatch
private dropHandler = (event: Event, dropEvent: DragManager.DropEvent, fieldKey: string) => {
- event.stopPropagation();
+ event.stopPropagation(); // prevent parent Doc from registering new position so that it snaps back into place
const droppedDocs = dropEvent.complete.docDragData?.droppedDocuments;
if (droppedDocs?.length) {
this.dataDoc[fieldKey] = droppedDocs[0];
@@ -47,6 +48,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps, C
private registerSliding = (e: React.PointerEvent<HTMLDivElement>, targetWidth: number) => {
setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, action(() => {
+ // on click, animate slider movement to the targetWidth
this._animating = "all 1s";
this.layoutDoc._clipWidth = targetWidth * 100 / this.props.PanelWidth();
setTimeout(action(() => this._animating = ""), 1000);
@@ -64,7 +66,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps, C
@undoBatch
clearDoc = (e: React.MouseEvent, fieldKey: string) => {
- e.stopPropagation;
+ e.stopPropagation; // prevent click event action (slider movement) in registerSliding
delete this.dataDoc[fieldKey];
}
@@ -72,7 +74,9 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps, C
const clipWidth = NumCast(this.layoutDoc._clipWidth) + "%";
const childProps: DocumentViewProps = { ...this.props, pointerEvents: false, parentActive: this.props.active };
const clearButton = (which: string) => {
- return <div className={`clear-button ${which}`} onPointerDown={e => e.stopPropagation()} onClick={e => this.clearDoc(e, `${which}Doc`)}>
+ return <div className={`clear-button ${which}`}
+ onPointerDown={e => e.stopPropagation()} // prevent triggering slider movement in registerSliding
+ onClick={e => this.clearDoc(e, `${which}Doc`)}>
<FontAwesomeIcon className={`clear-button ${which}`} icon={"times"} size="sm" />
</div>;
};
@@ -95,13 +99,14 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps, C
};
return (
- <div className={`comparisonBox${this.active() || SnappingManager.GetIsDragging() ? "-interactive" : ""}`}>
+ <div className={`comparisonBox${this.active() || SnappingManager.GetIsDragging() ? "-interactive" : ""}` /* change className to easily disable/enable pointer events in CSS */}>
{displayBox("after", 1, this.props.PanelWidth() - 5)}
<div className="clip-div" style={{ width: clipWidth, transition: this._animating, background: StrCast(this.layoutDoc._backgroundColor, "gray") }}>
{displayBox("before", 0, 5)}
</div>
- <div className="slide-bar" style={{ left: `calc(${clipWidth} - 0.5px)` }}>
+ <div className="slide-bar" style={{ left: `calc(${clipWidth} - 0.5px)` }}
+ onPointerDown={e => this.registerSliding(e, this.props.PanelWidth() / 2)} /* if clicked, return slide-bar to center */ >
<div className="slide-handle" />
</div>
</div >);
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index ef56e6fcd..126e9ac14 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -1,6 +1,6 @@
import { computed } from "mobx";
import { observer } from "mobx-react";
-import { Doc, Opt, Field } from "../../../fields/Doc";
+import { Doc, Opt, Field, AclSym, AclPrivate } from "../../../fields/Doc";
import { Cast, StrCast, NumCast } from "../../../fields/Types";
import { OmitKeys, Without, emptyPath } from "../../../Utils";
import DirectoryImportBox from "../../util/Import & Export/DirectoryImportBox";
@@ -185,7 +185,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
const bindings = this.CreateBindings(onClick, onInput);
// layoutFrame = splits.length > 1 ? splits[0] + splits[1].replace(/{([^{}]|(?R))*}/, replacer4) : ""; // might have been more elegant if javascript supported recursive patterns
- return (this.props.renderDepth > 12 || !layoutFrame || !this.layoutDoc) ? (null) :
+ return (this.props.renderDepth > 12 || !layoutFrame || !this.layoutDoc || this.layoutDoc[AclSym] === AclPrivate) ? (null) :
<ObserverJsxParser
key={42}
blacklistedAttrs={[]}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 0d06a8828..f9f453227 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -4,7 +4,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
import * as rp from "request-promise";
-import { Doc, DocListCast, HeightSym, Opt, WidthSym, DataSym } from "../../../fields/Doc";
+import { Doc, DocListCast, HeightSym, Opt, WidthSym, DataSym, AclSym, AclReadonly, AclPrivate } from "../../../fields/Doc";
import { Document } from '../../../fields/documentSchemas';
import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
@@ -37,7 +37,6 @@ import { ContextMenu } from "../ContextMenu";
import { ContextMenuProps } from '../ContextMenuItem';
import { DocComponent } from "../DocComponent";
import { EditableView } from '../EditableView';
-import { InkingControl } from '../InkingControl';
import { KeyphraseQueryView } from '../KeyphraseQueryView';
import { DocumentContentsView } from "./DocumentContentsView";
import "./DocumentView.scss";
@@ -45,6 +44,7 @@ import "./DocumentView.scss";
import { LinkAnchorBox } from './LinkAnchorBox';
import { RadialMenu } from './RadialMenu';
import React = require("react");
+import { undo } from 'prosemirror-history';
library.add(fa.faEdit, fa.faTrash, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faCompressArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faAlignCenter, fa.faCaretSquareRight,
fa.faSquare, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faLink, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock, fa.faLock, fa.faLaptopCode, fa.faMale,
@@ -332,7 +332,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
} else func();
} else if (this.Document["onClick-rawScript"] && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) {// bcz: hack? don't edit a script if you're clicking on a scripting box itself
const alias = Doc.MakeAlias(this.props.Document);
- Doc.makeCustomViewClicked(alias, undefined, "onClick");
+ DocUtils.makeCustomViewClicked(alias, undefined, "onClick");
this.props.addDocTab(alias, "onRight");
// UndoManager.RunInBatch(() => Doc.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick");
//ScriptBox.EditButtonScript("On Button Clicked ...", this.props.Document, "onClick", e.clientX, e.clientY), "on button click");
@@ -515,7 +515,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
// console.log(e.button)
// console.log(e.nativeEvent)
// continue if the event hasn't been canceled AND we are using a moues or this is has an onClick or onDragStart function (meaning it is a button document)
- if (!(InteractionUtils.IsType(e, InteractionUtils.MOUSETYPE) || InkingControl.Instance.selectedTool === InkTool.Highlighter || InkingControl.Instance.selectedTool === InkTool.Pen)) {
+ if (!(InteractionUtils.IsType(e, InteractionUtils.MOUSETYPE) || Doc.GetSelectedTool() === InkTool.Highlighter || Doc.GetSelectedTool() === InkTool.Pen)) {
if (!InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) {
e.stopPropagation();
// TODO: check here for panning/inking
@@ -546,7 +546,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
onPointerMove = (e: PointerEvent): void => {
if ((e as any).formattedHandled) { e.stopPropagation(); return; }
- if ((InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || InkingControl.Instance.selectedTool === InkTool.Highlighter || InkingControl.Instance.selectedTool === InkTool.Pen)) return;
+ if ((InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || Doc.GetSelectedTool() === InkTool.Highlighter || Doc.GetSelectedTool() === InkTool.Pen)) return;
if (e.cancelBubble && this.active) {
document.removeEventListener("pointermove", this.onPointerMove); // stop listening to pointerMove if something else has stopPropagated it (e.g., the MarqueeView)
}
@@ -684,6 +684,17 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
this.Document.lockedPosition = this.Document.lockedPosition ? undefined : true;
}
+ @undoBatch
+ @action
+ setAcl = (acl: "readOnly" | "addOnly" | "ownerOnly") => {
+ this.layoutDoc.ACL = this.dataDoc.ACL = acl;
+ DocListCast(this.dataDoc[Doc.LayoutFieldKey(this.dataDoc)]).map(d => {
+ if (d.author === Doc.CurrentUserEmail) d.ACL = acl;
+ const data = d[DataSym];
+ if (data && data.author === Doc.CurrentUserEmail) data.ACL = acl;
+ });
+ }
+
@action
onContextMenu = async (e: React.MouseEvent | Touch): Promise<void> => {
// the touch onContextMenu is button 0, the pointer onContextMenu is button 2
@@ -729,7 +740,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: this.toggleFollowInPlace, icon: "concierge-bell" });
onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link on Right", event: this.toggleFollowOnRight, icon: "concierge-bell" });
onClicks.push({ description: this.Document.isLinkButton || this.Document.onClick ? "Remove Click Behavior" : "Follow Link", event: this.toggleLinkButtonBehavior, icon: "concierge-bell" });
- onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => Doc.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "edit" });
+ onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "edit" });
!existingOnClick && cm.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" });
@@ -744,6 +755,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
const more = cm.findByDescription("More...");
console.log("[IN MORE] what is more? " + more)
const moreItems: ContextMenuProps[] = more && "subitems" in more ? more.subitems : [];
+ moreItems.push({ description: "Make Add Only", event: () => this.setAcl("addOnly"), icon: "concierge-bell" });
+ moreItems.push({ description: "Make Read Only", event: () => this.setAcl("readOnly"), icon: "concierge-bell" });
+ moreItems.push({ description: "Make Private", event: () => this.setAcl("ownerOnly"), icon: "concierge-bell" });
moreItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc), icon: "concierge-bell" });
moreItems.push({ description: `${this.Document._chromeStatus !== "disabled" ? "Hide" : "Show"} Chrome`, event: () => this.Document._chromeStatus = (this.Document._chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram" });
moreItems.push({ description: this.Document.lockedPosition ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.Document.lockedPosition) ? "unlock" : "lock" });
@@ -751,7 +765,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
if (!ClientUtils.RELEASE) {
// let copies: ContextMenuProps[] = [];
- moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" });
+ moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" });
// cm.addItem({ description: "Copy...", subitems: copies, icon: "copy" });
}
@@ -987,9 +1001,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
return this.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false;
}
childScaling = () => (this.layoutDoc._fitWidth ? this.props.PanelWidth() / this.nativeWidth : this.props.ContentScaling());
- panelWidth = () => this.props.PanelWidth();
- panelHeight = () => this.props.PanelHeight();
- screenToLocalTransform = () => this.props.ScreenToLocalTransform();
@computed get contents() {
TraceMobx();
return (<>
@@ -1010,10 +1021,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
addDocument={this.props.addDocument}
removeDocument={this.props.removeDocument}
moveDocument={this.props.moveDocument}
- ScreenToLocalTransform={this.screenToLocalTransform}
+ ScreenToLocalTransform={this.props.ScreenToLocalTransform}
renderDepth={this.props.renderDepth}
- PanelWidth={this.panelWidth}
- PanelHeight={this.panelHeight}
+ PanelWidth={this.props.PanelWidth}
+ PanelHeight={this.props.PanelHeight}
ignoreAutoHeight={this.props.ignoreAutoHeight}
focus={this.props.focus}
parentActive={this.props.parentActive}
@@ -1113,14 +1124,14 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
@computed get ignorePointerEvents() {
return this.props.pointerEvents === false ||
(this.Document.isBackground && !this.isSelected() && !SnappingManager.GetIsDragging()) ||
- (this.Document.type === DocumentType.INK && InkingControl.Instance.selectedTool !== InkTool.None);
+ (this.Document.type === DocumentType.INK && Doc.GetSelectedTool() !== InkTool.None);
}
@undoBatch
@action
setCustomView = (custom: boolean, layout: string): void => {
Doc.setNativeView(this.props.Document);
if (custom) {
- Doc.makeCustomViewClicked(this.props.Document, Docs.Create.StackingDocument, layout, undefined);
+ DocUtils.makeCustomViewClicked(this.props.Document, Docs.Create.StackingDocument, layout, undefined);
}
}
@observable _animateScalingTo = 0;
@@ -1144,6 +1155,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}
render() {
+ if (this.props.Document[AclSym] && this.props.Document[AclSym] === AclPrivate) return (null);
if (!(this.props.Document instanceof Doc)) return (null);
const backgroundColor = Doc.UserDoc().renderStyle === "comic" ? undefined : StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.Document.backgroundColor) || this.props.backgroundColor?.(this.Document);
const opacity = Cast(this.layoutDoc._opacity, "number", Cast(this.layoutDoc.opacity, "number", Cast(this.Document.opacity, "number", null)));
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 6913dfbc7..cabf30c13 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -192,7 +192,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps, ImageD
extractFaces = () => {
const converter = (results: any) => {
- return results.map((face: CognitiveServices.Image.Face) => Docs.Get.FromJson({ data: face, title: `Face: ${face.faceId}` })!);
+ return results.map((face: CognitiveServices.Image.Face) => Doc.Get.FromJson({ data: face, title: `Face: ${face.faceId}` })!);
};
this.url && CognitiveServices.Image.Appliers.ProcessImage(this.dataDoc, [this.fieldKey + "-faces"], this.url, Service.Face, converter);
}
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 956d6556b..3cbe3e494 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -99,9 +99,9 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
<div className="keyValuePair-td-key-container">
<button style={hover} className="keyValuePair-td-key-delete" onClick={undoBatch(() => {
if (Object.keys(props.Document).indexOf(props.fieldKey) !== -1) {
- props.Document[props.fieldKey] = undefined;
+ delete props.Document[props.fieldKey];
}
- else props.Document.proto![props.fieldKey] = undefined;
+ else delete props.Document.proto![props.fieldKey];
})}>
X
</button>
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 493f23dc4..fae216f17 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -248,7 +248,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
_pdfjsRequested = false;
render() {
const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField, null);
- if (this.props.isSelected() || this.props.renderDepth <= 1 || this.props.Document.scrollY !== undefined) this._everActive = true;
+ if (this.props.isSelected() || this.props.renderDepth <= 1 || this.props.Document._scrollY !== undefined) this._everActive = true;
if (pdfUrl && (this._everActive || this.props.Document._scrollTop || (this.dataDoc[this.props.fieldKey + "-nativeWidth"] && this.props.ScreenToLocalTransform().Scale < 2.5))) {
if (pdfUrl instanceof PdfField && this._pdf) {
return this.renderPdfView;
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index aeb77a894..dbc879920 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -11,7 +11,6 @@ import { DocumentManager } from "../../util/DocumentManager";
import { undoBatch } from "../../util/UndoManager";
import { CollectionDockingView } from "../collections/CollectionDockingView";
import { CollectionView, CollectionViewType } from "../collections/CollectionView";
-import { InkingControl } from "../InkingControl";
import { FieldView, FieldViewProps } from './FieldView';
import "./PresBox.scss";
import { ViewBoxBaseComponent } from "../DocComponent";
@@ -20,6 +19,7 @@ import { Docs } from "../../documents/Documents";
import { PrefetchProxy } from "../../../fields/Proxy";
import { ScriptField } from "../../../fields/ScriptField";
import { Scripting } from "../../util/Scripting";
+import { InkingStroke } from "../InkingStroke";
type PresBoxSchema = makeInterface<[typeof documentSchema]>;
const PresBoxDocument = makeInterface(documentSchema);
@@ -59,10 +59,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
next = () => {
this.updateCurrentPresentation();
const presTargetDoc = Cast(this.childDocs[this.itemIndex].presentationTargetDoc, Doc, null);
- const lastFrame = Cast(presTargetDoc.lastTimecode, "number", null);
- const curFrame = NumCast(presTargetDoc.currentTimecode);
+ const lastFrame = Cast(presTargetDoc.lastFrame, "number", null);
+ const curFrame = NumCast(presTargetDoc.currentFrame);
if (lastFrame !== undefined && curFrame < lastFrame) {
- presTargetDoc.currentTimecode = curFrame + 1;
+ presTargetDoc.transition = "all 1s";
+ setTimeout(() => presTargetDoc.transition = undefined, 1010);
+ presTargetDoc.currentFrame = curFrame + 1;
}
else if (this.childDocs[this.itemIndex + 1] !== undefined) {
let nextSelected = this.itemIndex + 1;
@@ -199,8 +201,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
if (index >= 0 && index < this.childDocs.length) {
this.rootDoc._itemIndex = index;
const presTargetDoc = Cast(this.childDocs[this.itemIndex].presentationTargetDoc, Doc, null);
- if (presTargetDoc.lastTimecode !== undefined) {
- presTargetDoc.currentTimecode = 0;
+ if (presTargetDoc.lastFrame !== undefined) {
+ presTargetDoc.currentFrame = 0;
}
if (!this.layoutDoc.presStatus) {
@@ -291,7 +293,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
selectElement = (doc: Doc) => this.gotoDocument(this.childDocs.indexOf(doc), NumCast(this.itemIndex));
getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight
panelHeight = () => this.props.PanelHeight() - 20;
- active = (outsideReaction?: boolean) => ((InkingControl.Instance.selectedTool === InkTool.None && !this.layoutDoc.isBackground) &&
+ active = (outsideReaction?: boolean) => ((Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc.isBackground) &&
(this.layoutDoc.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false)
render() {
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index 29e3c008a..d75b864cf 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -5,21 +5,19 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { action, computed, IReactionDisposer, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
import * as rp from 'request-promise';
+import { Doc } from "../../../fields/Doc";
import { documentSchema } from "../../../fields/documentSchemas";
-import { makeInterface, listSpec } from "../../../fields/Schema";
+import { listSpec, makeInterface } from "../../../fields/Schema";
import { Cast, NumCast } from "../../../fields/Types";
import { VideoField } from "../../../fields/URLField";
-import { emptyFunction, returnFalse, returnOne, Utils, returnZero } from "../../../Utils";
-import { Docs, DocUtils } from "../../documents/Documents";
+import { emptyFunction, returnFalse, returnOne, returnZero, Utils } from "../../../Utils";
+import { Docs } from "../../documents/Documents";
import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView";
import { ContextMenu } from "../ContextMenu";
import { ContextMenuProps } from "../ContextMenuItem";
import { ViewBoxBaseComponent } from "../DocComponent";
-import { InkingControl } from "../InkingControl";
import { FieldView, FieldViewProps } from './FieldView';
import "./ScreenshotBox.scss";
-import { Doc, WidthSym, HeightSym } from "../../../fields/Doc";
-import { OverlayView } from "../OverlayView";
const path = require('path');
type ScreenshotDocument = makeInterface<[typeof documentSchema]>;
@@ -134,7 +132,7 @@ export class ScreenshotBox extends ViewBoxBaseComponent<FieldViewProps, Screensh
}
@computed get content() {
- const interactive = InkingControl.Instance.selectedTool || !this.props.isSelected() ? "" : "-interactive";
+ const interactive = Doc.GetSelectedTool() || !this.props.isSelected() ? "" : "-interactive";
const style = "videoBox-content" + interactive;
return <video className={`${style}`} key="video" autoPlay={this._screenCapture} ref={this.setVideoRef}
style={{ width: this._screenCapture ? "100%" : undefined, height: this._screenCapture ? "100%" : undefined }}
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 9d02239fc..1e0a859d3 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -15,7 +15,6 @@ import { ContextMenu } from "../ContextMenu";
import { ContextMenuProps } from "../ContextMenuItem";
import { ViewBoxAnnotatableComponent } from "../DocComponent";
import { DocumentDecorations } from "../DocumentDecorations";
-import { InkingControl } from "../InkingControl";
import { FieldView, FieldViewProps } from './FieldView';
import "./VideoBox.scss";
import { documentSchema } from "../../../fields/documentSchemas";
@@ -229,7 +228,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
@computed get content() {
const field = Cast(this.dataDoc[this.fieldKey], VideoField);
- const interactive = InkingControl.Instance.selectedTool || !this.props.isSelected() ? "" : "-interactive";
+ const interactive = Doc.GetSelectedTool() || !this.props.isSelected() ? "" : "-interactive";
const style = "videoBox-content" + (this._fullScreen ? "-fullScreen" : "") + interactive;
return !field ? <div>Loading</div> :
<video className={`${style}`} key="video" autoPlay={this._screenCapture} ref={this.setVideoRef}
@@ -273,8 +272,8 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
this._reactionDisposer && this._reactionDisposer();
this._youtubeReactionDisposer && this._youtubeReactionDisposer();
this._reactionDisposer = reaction(() => this.layoutDoc.currentTimecode, () => !this._playing && this.Seek((this.layoutDoc.currentTimecode || 0)));
- this._youtubeReactionDisposer = reaction(() => [this.props.isSelected(), DocumentDecorations.Instance.Interacting, InkingControl.Instance.selectedTool], () => {
- const interactive = InkingControl.Instance.selectedTool === InkTool.None && this.props.isSelected(true) && !DocumentDecorations.Instance.Interacting;
+ this._youtubeReactionDisposer = reaction(() => [this.props.isSelected(), DocumentDecorations.Instance.Interacting, Doc.GetSelectedTool()], () => {
+ const interactive = Doc.GetSelectedTool() === InkTool.None && this.props.isSelected(true) && !DocumentDecorations.Instance.Interacting;
iframe.style.pointerEvents = interactive ? "all" : "none";
}, { fireImmediately: true });
};
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index f80cea941..fb9e57b51 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -15,7 +15,6 @@ import { DragManager } from "../../util/DragManager";
import { ImageUtils } from "../../util/Import & Export/ImageUtils";
import { ViewBoxAnnotatableComponent } from "../DocComponent";
import { DocumentDecorations } from "../DocumentDecorations";
-import { InkingControl } from "../InkingControl";
import { FieldView, FieldViewProps } from './FieldView';
import "./WebBox.scss";
import React = require("react");
@@ -58,15 +57,15 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
iframe.contentDocument.addEventListener('pointerdown', this.iframedown, false);
iframe.contentDocument.addEventListener('scroll', this.iframeScrolled, false);
this.layoutDoc.scrollHeight = iframe.contentDocument.children?.[0].scrollHeight || 1000;
- iframe.contentDocument.children[0].scrollTop = NumCast(this.layoutDoc.scrollTop);
- iframe.contentDocument.children[0].scrollLeft = NumCast(this.layoutDoc.scrollLeft);
+ iframe.contentDocument.children[0].scrollTop = NumCast(this.layoutDoc._scrollTop);
+ iframe.contentDocument.children[0].scrollLeft = NumCast(this.layoutDoc._scrollLeft);
}
this._reactionDisposer?.();
- this._reactionDisposer = reaction(() => ({ y: this.layoutDoc.scrollY, x: this.layoutDoc.scrollX }),
+ this._reactionDisposer = reaction(() => ({ y: this.layoutDoc._scrollY, x: this.layoutDoc._scrollX }),
({ x, y }) => {
if (y !== undefined) {
this._outerRef.current!.scrollTop = y;
- this.layoutDoc.scrollY = undefined;
+ this.layoutDoc._scrollY = undefined;
}
if (x !== undefined) {
this._outerRef.current!.scrollLeft = x;
@@ -83,8 +82,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
iframeScrolled = (e: any) => {
const scrollTop = e.target?.children?.[0].scrollTop;
const scrollLeft = e.target?.children?.[0].scrollLeft;
- this.layoutDoc.scrollTop = this._outerRef.current!.scrollTop = scrollTop;
- this.layoutDoc.scrollLeft = this._outerRef.current!.scrollLeft = scrollLeft;
+ this.layoutDoc._scrollTop = this._outerRef.current!.scrollTop = scrollTop;
+ this.layoutDoc._scrollLeft = this._outerRef.current!.scrollLeft = scrollLeft;
}
async componentDidMount() {
const urlField = Cast(this.dataDoc[this.props.fieldKey], WebField);
@@ -106,7 +105,9 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
} // else it's an HTMLfield
} else if (field?.url) {
const result = await WebRequest.get(Utils.CorsProxy(field.url.href));
- this.dataDoc.text = htmlToText.fromString(result.content);
+ if (result) {
+ this.dataDoc.text = htmlToText.fromString(result.content);
+ }
}
}
@@ -409,9 +410,9 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
view = <span className="webBox-htmlSpan" dangerouslySetInnerHTML={{ __html: field.html }} />;
} else if (field instanceof WebField) {
const url = this.layoutDoc.UseCors ? Utils.CorsProxy(field.url.href) : field.url.href;
- view = <iframe className="webBox-iframe" ref={this._iframeRef} src={url} onLoad={this.iframeLoaded} />;
+ view = <iframe className="webBox-iframe" enable-annotation={true} ref={this._iframeRef} src={url} onLoad={this.iframeLoaded} />;
} else {
- view = <iframe className="webBox-iframe" ref={this._iframeRef} src={"https://crossorigin.me/https://cs.brown.edu"} />;
+ view = <iframe className="webBox-iframe" enable-annotation={true} ref={this._iframeRef} src={"https://crossorigin.me/https://cs.brown.edu"} />;
}
return view;
}
@@ -423,7 +424,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
const frozen = !this.props.isSelected() || decInteracting;
return (<>
- <div className={"webBox-cont" + (this.props.isSelected() && InkingControl.Instance.selectedTool === InkTool.None && !decInteracting ? "-interactive" : "")}
+ <div className={"webBox-cont" + (this.props.isSelected() && Doc.GetSelectedTool() === InkTool.None && !decInteracting ? "-interactive" : "")}
onWheel={this.onPostWheel} onPointerDown={this.onPostPointer} onPointerMove={this.onPostPointer} onPointerUp={this.onPostPointer}>
{view}
</div>;
@@ -438,7 +439,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
{this.urlEditor()}
</>);
}
- scrollXf = () => this.props.ScreenToLocalTransform().translate(NumCast(this.layoutDoc.scrollLeft), NumCast(this.layoutDoc.scrollTop));
+ scrollXf = () => this.props.ScreenToLocalTransform().translate(NumCast(this.layoutDoc._scrollLeft), NumCast(this.layoutDoc._scrollTop));
render() {
return (<div className={`webBox-container`}
style={{
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss
index 477a2ca08..49114d967 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.scss
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss
@@ -95,6 +95,17 @@
.formattedTextBox-inner {
height: 100%;
white-space: pre-wrap;
+ hr {
+ display: block;
+ unicode-bidi: isolate;
+ margin-block-start: 0.5em;
+ margin-block-end: 0.5em;
+ margin-inline-start: auto;
+ margin-inline-end: auto;
+ overflow: hidden;
+ border-style: inset;
+ border-width: 1px;
+ }
}
// .menuicon {
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 411eebf4f..130931b24 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -52,14 +52,12 @@ import { ContextMenu } from '../../ContextMenu';
import { ContextMenuProps } from '../../ContextMenuItem';
import { ViewBoxAnnotatableComponent } from "../../DocComponent";
import { DocumentButtonBar } from '../../DocumentButtonBar';
-import { InkingControl } from "../../InkingControl";
import { AudioBox } from '../AudioBox';
import { FieldView, FieldViewProps } from "../FieldView";
import "./FormattedTextBox.scss";
import { FormattedTextBoxComment, formattedTextBoxCommentPlugin } from './FormattedTextBoxComment';
import React = require("react");
-import { ScriptField } from '../../../../fields/ScriptField';
-import GoogleAuthenticationManager from '../../../apis/GoogleAuthenticationManager';
+import { InkingStroke } from '../../InkingStroke';
library.add(faEdit);
library.add(faSmile, faTextHeight, faUpload);
@@ -479,11 +477,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
changeItems.push({
description: StrCast(note.title), event: undoBatch(() => {
Doc.setNativeView(this.rootDoc);
- Doc.makeCustomViewClicked(this.rootDoc, Docs.Create.TreeDocument, StrCast(note.title), note);
+ DocUtils.makeCustomViewClicked(this.rootDoc, Docs.Create.TreeDocument, StrCast(note.title), note);
}), icon: "eye"
});
});
- changeItems.push({ description: "FreeForm", event: undoBatch(() => Doc.makeCustomViewClicked(this.rootDoc, Docs.Create.FreeformDocument, "freeform"), "change view"), icon: "eye" });
+ changeItems.push({ description: "FreeForm", event: undoBatch(() => DocUtils.makeCustomViewClicked(this.rootDoc, Docs.Create.FreeformDocument, "freeform"), "change view"), icon: "eye" });
!change && cm.addItem({ description: "Change Perspective...", subitems: changeItems, icon: "external-link-alt" });
}
@@ -721,7 +719,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
},
{ fireImmediately: true }
);
- this._disposers.scroll = reaction(() => NumCast(this.layoutDoc.scrollPos),
+ this._disposers.scroll = reaction(() => NumCast(this.layoutDoc._scrollTop),
pos => this._scrollRef.current && this._scrollRef.current.scrollTo({ top: pos }), { fireImmediately: true }
);
@@ -869,7 +867,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
const marks = [...node.marks];
const linkIndex = marks.findIndex(mark => mark.type.name === "link");
- const link = view.state.schema.mark(view.state.schema.marks.link, { href: `http://localhost:1050/doc/${linkId}`, location: "onRight", title: title, docref: true });
+ const link = view.state.schema.mark(view.state.schema.marks.link, { href: Utils.prepend(`/doc/${linkId}`), location: "onRight", title: title, docref: true });
marks.splice(linkIndex === -1 ? 0 : linkIndex, 1, link);
return node.mark(marks);
}
@@ -1165,7 +1163,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
onscrolled = (ev: React.UIEvent) => {
- this.layoutDoc.scrollPos = this._scrollRef.current!.scrollTop;
+ this.layoutDoc._scrollTop = this._scrollRef.current!.scrollTop;
}
@action
tryUpdateHeight(limitHeight?: number) {
@@ -1204,7 +1202,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
TraceMobx();
const scale = this.props.ContentScaling() * NumCast(this.layoutDoc.scale, 1);
const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : "";
- const interactive = InkingControl.Instance.selectedTool || this.layoutDoc.isBackground;
+ const interactive = Doc.GetSelectedTool() || this.layoutDoc.isBackground;
if (this.props.isSelected()) {
this._editorView && RichTextMenu.Instance.updateFromDash(this._editorView, undefined, this.props);
} else if (FormattedTextBoxComment.textBox === this) {
@@ -1259,7 +1257,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
</div>
{!this.layoutDoc._showSidebar ? (null) : this.sidebarWidthPercent === "0%" ?
<div className="formattedTextBox-sidebar-handle" onPointerDown={this.sidebarDown} /> :
- <div className={"formattedTextBox-sidebar" + (InkingControl.Instance.selectedTool !== InkTool.None ? "-inking" : "")}
+ <div className={"formattedTextBox-sidebar" + (Doc.GetSelectedTool() !== InkTool.None ? "-inking" : "")}
style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
<CollectionFreeFormView {...this.props}
PanelHeight={this.props.PanelHeight}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index d47ae63af..59a6045ab 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -183,7 +183,7 @@ export class FormattedTextBoxComment {
const anchor = FieldValue(Doc.AreProtosEqual(FieldValue(Cast(linkDoc.anchor1, Doc)), textBox.dataDoc) ? Cast(linkDoc.anchor2, Doc) : (Cast(linkDoc.anchor1, Doc)) || linkDoc);
const target = anchor?.annotationOn ? await DocCastAsync(anchor.annotationOn) : anchor;
if (anchor !== target && anchor && target) {
- target.scrollY = NumCast(anchor?.y);
+ target._scrollY = NumCast(anchor?.y);
}
if (target) {
ReactDOM.render(<ContentFittingDocumentView
diff --git a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
index dd610944a..444a8a4c0 100644
--- a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
+++ b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
@@ -141,15 +141,12 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, props: any
const originalDoc = layoutDoc.rootDocument || layoutDoc;
if (force || props.Document._singleLine) {
const layoutKey = StrCast(originalDoc.layoutKey);
- const newDoc = Docs.Create.TextDocument("", {
- layout: Cast(originalDoc.layout, Doc, null) || FormattedTextBox.DefaultLayout,
- layoutKey,
- _singleLine: BoolCast(originalDoc._singleLine),
- x: NumCast(originalDoc.x) + NumCast(originalDoc._width) + 10, y: NumCast(originalDoc.y), _width: NumCast(layoutDoc._width), _height: NumCast(layoutDoc._height)
- });
+ const newDoc = Doc.MakeCopy(originalDoc, true);
+ newDoc.y = NumCast(originalDoc.y) + NumCast(originalDoc._height) + 10;
if (layoutKey !== "layout" && originalDoc[layoutKey] instanceof Doc) {
newDoc[layoutKey] = originalDoc[layoutKey];
}
+ Doc.GetProto(newDoc).text = undefined;
FormattedTextBox.SelectOnLoad = newDoc[Id];
props.addDocument(newDoc);
return true;
@@ -168,15 +165,12 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, props: any
const originalDoc = layoutDoc.rootDocument || layoutDoc;
if (originalDoc instanceof Doc) {
const layoutKey = StrCast(originalDoc.layoutKey);
- const newDoc = Docs.Create.TextDocument("", {
- layout: Cast(originalDoc.layout, Doc, null) || FormattedTextBox.DefaultLayout,
- layoutKey,
- _singleLine: BoolCast(originalDoc._singleLine),
- x: NumCast(originalDoc.x), y: NumCast(originalDoc.y) + NumCast(originalDoc._height) + 10, _width: NumCast(layoutDoc._width), _height: NumCast(layoutDoc._height)
- });
+ const newDoc = Doc.MakeCopy(originalDoc, true);
+ newDoc.x = NumCast(originalDoc.x) + NumCast(originalDoc._width) + 10;
if (layoutKey !== "layout" && originalDoc[layoutKey] instanceof Doc) {
newDoc[layoutKey] = originalDoc[layoutKey];
}
+ Doc.GetProto(newDoc).text = undefined;
FormattedTextBox.SelectOnLoad = newDoc[Id];
props.addDocument(newDoc);
}