aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/views/InkingCanvas.scss3
-rw-r--r--src/client/views/nodes/DocumentView.tsx92
-rw-r--r--src/client/views/nodes/VideoBox.scss5
3 files changed, 97 insertions, 3 deletions
diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss
index 9cc220a1d..8f32652ed 100644
--- a/src/client/views/InkingCanvas.scss
+++ b/src/client/views/InkingCanvas.scss
@@ -8,7 +8,8 @@
position: absolute;
width: 100%;
height: 100%;
- z-index: -1; // allows annotations to appear on videos when screen is full-size & ...
+ background: inherit;
+ //z-index: -1; // allows annotations to appear on videos when screen is full-size & ...
}
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index a7e78a7e8..c217c9d86 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,6 +1,6 @@
import { library } from '@fortawesome/fontawesome-svg-core';
import * as fa from '@fortawesome/free-solid-svg-icons';
-import { action, computed, runInAction, trace } from "mobx";
+import { action, computed, runInAction, trace, observable } from "mobx";
import { observer } from "mobx-react";
import * as rp from "request-promise";
import { Doc, DocListCast, DocListCastAsync, Opt } from "../../../new_fields/Doc";
@@ -103,6 +103,7 @@ export const documentSchema = createSchema({
height: "number", // "
backgroundColor: "string", // background color of document
opacity: "number", // opacity of document
+ //links: listSpec(Doc), // computed (readonly) list of links associated with this document
dropAction: "string", // override specifying what should happen when this document is dropped (can be "alias" or "copy")
removeDropProperties: listSpec("string"), // properties that should be removed from the alias/copy/etc of this document when it is dropped
onClick: ScriptField, // script to run when document is clicked (can be overriden by an onClick prop)
@@ -695,6 +696,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick}
onPointerEnter={() => Doc.BrushDoc(this.props.Document)} onPointerLeave={() => Doc.UnBrushDoc(this.props.Document)}
>
+ {this.props.Document.links && DocListCast(this.props.Document.links).map((d, i) => <DocuLink view={this} link={d} index={i} />)}
{!showTitle && !showCaption ?
this.Document.searchFields ?
(<div className="documentView-searchWrapper">
@@ -718,6 +720,94 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}
}
+
+interface DocuLinkProps {
+ view: DocumentView;
+ link: Doc;
+ index: number;
+}
+
+@observer
+export class DocuLink extends React.Component<DocuLinkProps> {
+ _downx = 0;
+ _downy = 0;
+ @observable _x = 0;
+ @observable _y = 0;
+
+ constructor(props: DocuLinkProps) {
+ super(props);
+ }
+
+ clamp(n: number, lower: number, upper: number) {
+ return Math.max(lower, Math.min(upper, n));
+ }
+
+ getNearestPointInPerimeter(l: number, t: number, w: number, h: number, x: number, y: number) {
+ var r = l + w,
+ b = t + h;
+
+ var x = this.clamp(x, l, r),
+ y = this.clamp(y, t, b);
+
+ var dl = Math.abs(x - l),
+ dr = Math.abs(x - r),
+ dt = Math.abs(y - t),
+ db = Math.abs(y - b);
+
+ var m = Math.min(dl, dr, dt, db);
+
+ return (m === dt) ? [x, t] :
+ (m === db) ? [x, b] :
+ (m === dl) ? [l, y] : [r, y];
+ }
+
+ get linkEndpoint() {
+ return Doc.AreProtosEqual(this.props.view.props.Document, Cast(this.props.link.anchor1, Doc) as Doc) ?
+ "anchor1" : "anchor2";
+ }
+ get linkOtherEndpoint() {
+ return !Doc.AreProtosEqual(this.props.view.props.Document, Cast(this.props.link.anchor1, Doc) as Doc) ?
+ "anchor1" : "anchor2";
+ }
+
+ onPointerDown = (e: React.PointerEvent) => {
+ this._downx = e.clientX;
+ this._downy = e.clientY;
+ document.removeEventListener("pointermove", this.onPointerMove);
+ document.removeEventListener("pointerup", this.onPointerUp);
+ document.addEventListener("pointermove", this.onPointerMove);
+ document.addEventListener("pointerup", this.onPointerUp);
+ e.stopPropagation();
+ }
+ onPointerMove = action((e: PointerEvent) => {
+ if (this.props.view.ContentDiv && (Math.abs(e.clientX - this._downx) > 3 || Math.abs(e.clientY - this._downy) > 3)) {
+ let bounds = this.props.view.ContentDiv.getBoundingClientRect();
+ let pt = this.getNearestPointInPerimeter(bounds.left - 25, bounds.top - 25, bounds.width, bounds.height, e.clientX, e.clientY);
+ this.props.link[this.linkEndpoint + "_x"] = (pt[0] - bounds.left) / bounds.width * 100;
+ this.props.link[this.linkEndpoint + "_y"] = (pt[1] - bounds.top) / bounds.height * 100;
+ }
+ })
+ onPointerUp = (e: PointerEvent) => {
+ document.removeEventListener("pointermove", this.onPointerMove);
+ document.removeEventListener("pointerup", this.onPointerUp);
+ }
+ onClick = (e: React.MouseEvent) => {
+ if (Math.abs(e.clientX - this._downx) < 3 && Math.abs(e.clientY - this._downy) < 3) {
+ DocumentManager.Instance.FollowLink(this.props.link, this.props.view.props.Document, document => this.props.view.props.addDocTab(document, undefined, "inTab"), false);
+ }
+ e.stopPropagation();
+ }
+ render() {
+ return <div onPointerDown={this.onPointerDown} title={StrCast((this.props.link[this.linkOtherEndpoint]! as Doc).title)} style={{
+ position: "absolute", background: "lightblue", width: "25px", height: "25px", borderRadius: "20px",
+ left: `${NumCast(this.props.link[this.linkEndpoint + "_x"], 100)}%`, top: `${NumCast(this.props.link[this.linkEndpoint + "_y"], 100)}%`
+ }} >
+ {this.props.index}
+ </div>
+ }
+}
+
+
export async function swapViews(doc: Doc, newLayoutField: string, oldLayoutField: string, oldLayout?: Doc) {
let oldLayoutExt = oldLayout || await Cast(doc[oldLayoutField], Doc);
if (oldLayoutExt) {
diff --git a/src/client/views/nodes/VideoBox.scss b/src/client/views/nodes/VideoBox.scss
index 48623eaaf..5829c1bd9 100644
--- a/src/client/views/nodes/VideoBox.scss
+++ b/src/client/views/nodes/VideoBox.scss
@@ -1,11 +1,14 @@
.videoBox-container {
pointer-events: all;
+ .inkingCanvas-paths-markers {
+ opacity : 0.4; // we shouldn't have to do this, but since chrome crawls to a halt with z-index unset in videoBox-content, this is a workaround
+ }
}
.videoBox-content-YouTube, .videoBox-content-YouTube-fullScreen,
.videoBox-content, .videoBox-content-interactive, .videoBox-cont-fullScreen {
width: 100%;
- z-index: 0; // logically this should be 0 (or unset) which would give us transparent brush strokes over videos. However, this makes Chrome crawl to a halt
+ z-index: -1; // 0; // logically this should be 0 (or unset) which would give us transparent brush strokes over videos. However, this makes Chrome crawl to a halt
position: absolute;
}