From 37f327ab659e6fa1221f9f4ed7649402c5dedc00 Mon Sep 17 00:00:00 2001
From: yipstanley <stanley_yip@brown.edu>
Date: Wed, 19 Jun 2019 11:24:32 -0400
Subject: aspect ratio, dragging, and full screen scrolling fixed

---
 src/client/views/pdf/Page.tsx | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

(limited to 'src/client/views/pdf/Page.tsx')

diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx
index a19b64eda..2697c9eee 100644
--- a/src/client/views/pdf/Page.tsx
+++ b/src/client/views/pdf/Page.tsx
@@ -51,7 +51,6 @@ export default class Page extends React.Component<IPageProps> {
     private _marquee: React.RefObject<HTMLDivElement>;
     private _curly: React.RefObject<HTMLImageElement>;
     private _marqueeing: boolean = false;
-    private _dragging: boolean = false;
     private _reactionDisposer?: IReactionDisposer;
 
     constructor(props: IPageProps) {
@@ -151,13 +150,9 @@ export default class Page extends React.Component<IPageProps> {
      */
     @action
     startDrag = (e: PointerEvent): void => {
-        // the first 5 lines is a hack to prevent text selection while dragging
         e.preventDefault();
         e.stopPropagation();
-        if (this._dragging) {
-            return;
-        }
-        this._dragging = true;
+        console.log("dragging");
         let thisDoc = this.props.parent.Document;
         // document that this annotation is linked to
         let targetDoc = Docs.TextDocument({ width: 200, height: 200, title: "New Annotation" });
@@ -179,7 +174,6 @@ export default class Page extends React.Component<IPageProps> {
     endDrag = (e: PointerEvent): void => {
         // document.removeEventListener("pointermove", this.startDrag);
         // document.removeEventListener("pointerup", this.endDrag);
-        this._dragging = false;
         e.stopPropagation();
     }
 
@@ -195,6 +189,8 @@ export default class Page extends React.Component<IPageProps> {
             // document.addEventListener("pointerup", this.endDrag);
         }
         else if (e.button === 0) {
+            PDFMenu.Instance.StartDrag = this.startDrag;
+            PDFMenu.Instance.Highlight = this.highlight;
             PDFMenu.Instance.fadeOut(true);
             let target: any = e.target;
             if (target && target.parentElement === this._textLayer.current) {
-- 
cgit v1.2.3-70-g09d2


From c056adeca11f35972b5f75c6b1cc31292d5765d4 Mon Sep 17 00:00:00 2001
From: yipstanley <stanley_yip@brown.edu>
Date: Wed, 19 Jun 2019 11:47:20 -0400
Subject: push

---
 src/client/views/pdf/PDFViewer.tsx | 316 ++++++++++++++++++-------------------
 src/client/views/pdf/Page.tsx      |  67 +-------
 2 files changed, 154 insertions(+), 229 deletions(-)

(limited to 'src/client/views/pdf/Page.tsx')

diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 67278b1eb..f0e55705d 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -19,6 +19,7 @@ import Page from "./Page";
 import "./PDFViewer.scss";
 import React = require("react");
 import PDFMenu from "./PDFMenu";
+import { UndoManager } from "../../util/UndoManager";
 
 export const scale = 2;
 interface IPDFViewerProps {
@@ -190,7 +191,7 @@ class Viewer extends React.Component<IViewerProps> {
         if (this._isPage[page] !== "none") {
             this._isPage[page] = "none";
             this._visibleElements[page] = (
-                <div key={`placeholder-${page}`} className="pdfviewer-placeholder"
+                <div key={`${this.props.url}-placeholder-${page + 1}`} className="pdfviewer-placeholder"
                     style={{ width: this._pageSizes[page].width, height: this._pageSizes[page].height }} />
             );
         }
@@ -204,11 +205,11 @@ class Viewer extends React.Component<IViewerProps> {
                     pdf={this.props.pdf}
                     page={page}
                     numPages={this.props.pdf.numPages}
-                    key={`rendered-${page + 1}`}
+                    key={`${this.props.url}-rendered-${page + 1}`}
                     name={`${this.props.pdf.fingerprint + `-page${page + 1}`}`}
                     pageLoaded={this.pageLoaded}
                     parent={this.props.parent}
-                    makePin={this.createPinAnnotation}
+                    makePin={emptyFunction}
                     renderAnnotations={this.renderAnnotations}
                     createAnnotation={this.createAnnotation}
                     sendAnnotations={this.receiveAnnotations}
@@ -285,27 +286,27 @@ class Viewer extends React.Component<IViewerProps> {
         return this._savedAnnotations.getValue(page);
     }
 
-    createPinAnnotation = (x: number, y: number, page: number): void => {
-        let targetDoc = Docs.TextDocument({ width: 100, height: 50, title: "New Pin Annotation" });
-        let pinAnno = new Doc();
-        pinAnno.x = x;
-        pinAnno.y = y + this.getScrollFromPage(page);
-        pinAnno.width = pinAnno.height = PinRadius;
-        pinAnno.page = page;
-        pinAnno.target = targetDoc;
-        pinAnno.type = AnnotationTypes.Pin;
-        // this._annotations.push(pinAnno);
-        let annoDoc = new Doc();
-        annoDoc.annotations = new List<Doc>([pinAnno]);
-        let annotations = DocListCast(this.props.parent.Document.annotations);
-        if (annotations && annotations.length) {
-            annotations.push(annoDoc);
-            this.props.parent.Document.annotations = new List<Doc>(annotations);
-        }
-        else {
-            this.props.parent.Document.annotations = new List<Doc>([annoDoc]);
-        }
-    }
+    // createPinAnnotation = (x: number, y: number, page: number): void => {
+    //     let targetDoc = Docs.TextDocument({ width: 100, height: 50, title: "New Pin Annotation" });
+    //     let pinAnno = new Doc();
+    //     pinAnno.x = x;
+    //     pinAnno.y = y + this.getScrollFromPage(page);
+    //     pinAnno.width = pinAnno.height = PinRadius;
+    //     pinAnno.page = page;
+    //     pinAnno.target = targetDoc;
+    //     pinAnno.type = AnnotationTypes.Pin;
+    //     // this._annotations.push(pinAnno);
+    //     let annoDoc = new Doc();
+    //     annoDoc.annotations = new List<Doc>([pinAnno]);
+    //     let annotations = DocListCast(this.props.parent.Document.annotations);
+    //     if (annotations && annotations.length) {
+    //         annotations.push(annoDoc);
+    //         this.props.parent.Document.annotations = new List<Doc>(annotations);
+    //     }
+    //     else {
+    //         this.props.parent.Document.annotations = new List<Doc>([annoDoc]);
+    //     }
+    // }
 
     // get the page index that the vertical offset passed in is on
     getPageFromScroll = (vOffset: number) => {
@@ -339,26 +340,6 @@ class Viewer extends React.Component<IViewerProps> {
             else {
                 this._savedAnnotations.setValue(page, [div]);
             }
-            PDFMenu.Instance.StartDrag = this.startDrag;
-        }
-    }
-
-    startDrag = (e: PointerEvent) => {
-        e.preventDefault();
-        e.stopPropagation();
-        let thisDoc = this.props.parent.Document;
-        // document that this annotation is linked to
-        let targetDoc = Docs.TextDocument({ width: 200, height: 200, title: "New Annotation" });
-        targetDoc.targetPage = Math.min(...this._savedAnnotations.keys());
-        let annotationDoc = this.makeAnnotationDocument(targetDoc, 1, "red");
-        let dragData = new DragManager.AnnotationDragData(thisDoc, annotationDoc, targetDoc);
-        if (this._annotationLayer.current) {
-            DragManager.StartAnnotationDrag([this._annotationLayer.current], dragData, e.pageX, e.pageY, {
-                handlers: {
-                    dragComplete: action(emptyFunction),
-                },
-                hideSource: false
-            });
         }
     }
 
@@ -367,8 +348,8 @@ class Viewer extends React.Component<IViewerProps> {
         let res = annotationDocs.map(a => {
             let type = NumCast(a.type);
             switch (type) {
-                case AnnotationTypes.Pin:
-                    return <PinAnnotation parent={this} document={a} x={NumCast(a.x)} y={NumCast(a.y)} width={a[WidthSym]()} height={a[HeightSym]()} key={a[Id]} />;
+                // case AnnotationTypes.Pin:
+                //     return <PinAnnotation parent={this} document={a} x={NumCast(a.x)} y={NumCast(a.y)} width={a[WidthSym]()} height={a[HeightSym]()} key={a[Id]} />;
                 case AnnotationTypes.Region:
                     return <RegionAnnotation parent={this} document={a} x={NumCast(a.x)} y={NumCast(a.y)} width={a[WidthSym]()} height={a[HeightSym]()} key={a[Id]} />;
                 default:
@@ -399,7 +380,7 @@ class Viewer extends React.Component<IViewerProps> {
 }
 
 export enum AnnotationTypes {
-    Region, Pin
+    Region
 }
 
 interface IAnnotationProps {
@@ -411,132 +392,139 @@ interface IAnnotationProps {
     document: Doc;
 }
 
-@observer
-class PinAnnotation extends React.Component<IAnnotationProps> {
-    @observable private _backgroundColor: string = "green";
-    @observable private _display: string = "initial";
-
-    private _mainCont: React.RefObject<HTMLDivElement>;
-
-    constructor(props: IAnnotationProps) {
-        super(props);
-        this._mainCont = React.createRef();
-    }
-
-    componentDidMount = () => {
-        let selected = this.props.document.selected;
-        if (!BoolCast(selected)) {
-            runInAction(() => {
-                this._backgroundColor = "red";
-                this._display = "none";
-            });
-        }
-        if (selected) {
-            if (BoolCast(selected)) {
-                runInAction(() => {
-                    this._backgroundColor = "green";
-                    this._display = "initial";
-                });
-            }
-            else {
-                runInAction(() => {
-                    this._backgroundColor = "red";
-                    this._display = "none";
-                });
-            }
-        }
-        else {
-            runInAction(() => {
-                this._backgroundColor = "red";
-                this._display = "none";
-            });
-        }
-    }
-
-    @action
-    pointerDown = (e: React.PointerEvent) => {
-        let selected = this.props.document.selected;
-        if (selected && BoolCast(selected)) {
-            this._backgroundColor = "red";
-            this._display = "none";
-            this.props.document.selected = false;
-        }
-        else {
-            this._backgroundColor = "green";
-            this._display = "initial";
-            this.props.document.selected = true;
-        }
-        e.preventDefault();
-        e.stopPropagation();
-    }
-
-    @action
-    doubleClick = (e: React.MouseEvent) => {
-        if (this._mainCont.current) {
-            let annotations = DocListCast(this.props.parent.props.parent.Document.annotations);
-            if (annotations && annotations.length) {
-                let index = annotations.indexOf(this.props.document);
-                annotations.splice(index, 1);
-                this.props.parent.props.parent.Document.annotations = new List<Doc>(annotations);
-            }
-            // this._mainCont.current.childNodes.forEach(e => e.remove());
-            this._mainCont.current.style.display = "none";
-            // if (this._mainCont.current.parentElement) {
-            //     this._mainCont.current.remove();
-            // }
-        }
-        e.stopPropagation();
-    }
-
-    render() {
-        let targetDoc = Cast(this.props.document.target, Doc);
-        if (targetDoc instanceof Doc) {
-            return (
-                <div className="pdfViewer-pinAnnotation" onPointerDown={this.pointerDown}
-                    onDoubleClick={this.doubleClick} ref={this._mainCont}
-                    style={{
-                        top: this.props.y * scale - PinRadius / 2, left: this.props.x * scale - PinRadius / 2, width: PinRadius,
-                        height: PinRadius, pointerEvents: "all", backgroundColor: this._backgroundColor
-                    }}>
-                    <div style={{
-                        position: "absolute", top: "25px", left: "25px", transform: "scale(3)", transformOrigin: "top left",
-                        display: this._display, width: targetDoc[WidthSym](), height: targetDoc[HeightSym]()
-                    }}>
-                        <DocumentView Document={targetDoc}
-                            ContainingCollectionView={undefined}
-                            ScreenToLocalTransform={this.props.parent.props.parent.props.ScreenToLocalTransform}
-                            isTopMost={false}
-                            ContentScaling={() => 1}
-                            PanelWidth={() => NumCast(this.props.parent.props.parent.Document.nativeWidth)}
-                            PanelHeight={() => NumCast(this.props.parent.props.parent.Document.nativeHeight)}
-                            focus={emptyFunction}
-                            selectOnLoad={false}
-                            parentActive={this.props.parent.props.parent.props.active}
-                            whenActiveChanged={this.props.parent.props.parent.props.whenActiveChanged}
-                            bringToFront={emptyFunction}
-                            addDocTab={this.props.parent.props.parent.props.addDocTab}
-                        />
-                    </div>
-                </div >
-            );
-        }
-        return null;
-    }
-}
+// @observer
+// class PinAnnotation extends React.Component<IAnnotationProps> {
+//     @observable private _backgroundColor: string = "green";
+//     @observable private _display: string = "initial";
+
+//     private _mainCont: React.RefObject<HTMLDivElement>;
+
+//     constructor(props: IAnnotationProps) {
+//         super(props);
+//         this._mainCont = React.createRef();
+//     }
+
+//     componentDidMount = () => {
+//         let selected = this.props.document.selected;
+//         if (!BoolCast(selected)) {
+//             runInAction(() => {
+//                 this._backgroundColor = "red";
+//                 this._display = "none";
+//             });
+//         }
+//         if (selected) {
+//             if (BoolCast(selected)) {
+//                 runInAction(() => {
+//                     this._backgroundColor = "green";
+//                     this._display = "initial";
+//                 });
+//             }
+//             else {
+//                 runInAction(() => {
+//                     this._backgroundColor = "red";
+//                     this._display = "none";
+//                 });
+//             }
+//         }
+//         else {
+//             runInAction(() => {
+//                 this._backgroundColor = "red";
+//                 this._display = "none";
+//             });
+//         }
+//     }
+
+//     @action
+//     pointerDown = (e: React.PointerEvent) => {
+//         let selected = this.props.document.selected;
+//         if (selected && BoolCast(selected)) {
+//             this._backgroundColor = "red";
+//             this._display = "none";
+//             this.props.document.selected = false;
+//         }
+//         else {
+//             this._backgroundColor = "green";
+//             this._display = "initial";
+//             this.props.document.selected = true;
+//         }
+//         e.preventDefault();
+//         e.stopPropagation();
+//     }
+
+//     @action
+//     doubleClick = (e: React.MouseEvent) => {
+//         if (this._mainCont.current) {
+//             let annotations = DocListCast(this.props.parent.props.parent.Document.annotations);
+//             if (annotations && annotations.length) {
+//                 let index = annotations.indexOf(this.props.document);
+//                 annotations.splice(index, 1);
+//                 this.props.parent.props.parent.Document.annotations = new List<Doc>(annotations);
+//             }
+//             // this._mainCont.current.childNodes.forEach(e => e.remove());
+//             this._mainCont.current.style.display = "none";
+//             // if (this._mainCont.current.parentElement) {
+//             //     this._mainCont.current.remove();
+//             // }
+//         }
+//         e.stopPropagation();
+//     }
+
+//     render() {
+//         let targetDoc = Cast(this.props.document.target, Doc);
+//         if (targetDoc instanceof Doc) {
+//             return (
+//                 <div className="pdfViewer-pinAnnotation" onPointerDown={this.pointerDown}
+//                     onDoubleClick={this.doubleClick} ref={this._mainCont}
+//                     style={{
+//                         top: this.props.y * scale - PinRadius / 2, left: this.props.x * scale - PinRadius / 2, width: PinRadius,
+//                         height: PinRadius, pointerEvents: "all", backgroundColor: this._backgroundColor
+//                     }}>
+//                     <div style={{
+//                         position: "absolute", top: "25px", left: "25px", transform: "scale(3)", transformOrigin: "top left",
+//                         display: this._display, width: targetDoc[WidthSym](), height: targetDoc[HeightSym]()
+//                     }}>
+//                         <DocumentView Document={targetDoc}
+//                             ContainingCollectionView={undefined}
+//                             ScreenToLocalTransform={this.props.parent.props.parent.props.ScreenToLocalTransform}
+//                             isTopMost={false}
+//                             ContentScaling={() => 1}
+//                             PanelWidth={() => NumCast(this.props.parent.props.parent.Document.nativeWidth)}
+//                             PanelHeight={() => NumCast(this.props.parent.props.parent.Document.nativeHeight)}
+//                             focus={emptyFunction}
+//                             selectOnLoad={false}
+//                             parentActive={this.props.parent.props.parent.props.active}
+//                             whenActiveChanged={this.props.parent.props.parent.props.whenActiveChanged}
+//                             bringToFront={emptyFunction}
+//                             addDocTab={this.props.parent.props.parent.props.addDocTab}
+//                         />
+//                     </div>
+//                 </div >
+//             );
+//         }
+//         return null;
+//     }
+// }
 
 class RegionAnnotation extends React.Component<IAnnotationProps> {
     @observable private _backgroundColor: string = "red";
 
-    onPointerDown = (e: React.MouseEvent) => {
-        let targetDoc = Cast(this.props.document.target, Doc, null);
-        if (targetDoc) {
-            DocumentManager.Instance.jumpToDocument(targetDoc);
+    onPointerDown = (e: React.PointerEvent) => {
+        if (e.button === 0) {
+            let targetDoc = Cast(this.props.document.target, Doc, null);
+            if (targetDoc) {
+                DocumentManager.Instance.jumpToDocument(targetDoc);
+            }
         }
+        // if (e.button === 2) {
+        //     console.log("right");
+        //     e.stopPropagation();
+        //     e.preventDefault();
+        // }
     }
 
     render() {
         return (
-            <div className="pdfViewer-annotationBox" onClick={this.onPointerDown}
+            <div className="pdfViewer-annotationBox" onPointerDown={this.onPointerDown}
                 style={{ top: this.props.y * scale, left: this.props.x * scale, width: this.props.width * scale, height: this.props.height * scale, pointerEvents: "all", backgroundColor: StrCast(this.props.document.color) }}></div>
         );
     }
diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx
index 2697c9eee..39e737c32 100644
--- a/src/client/views/pdf/Page.tsx
+++ b/src/client/views/pdf/Page.tsx
@@ -15,6 +15,7 @@ import { listSpec } from "../../../new_fields/Schema";
 import { menuBar } from "prosemirror-menu";
 import { AnnotationTypes, PDFViewer, scale } from "./PDFViewer";
 import PDFMenu from "./PDFMenu";
+import { UndoManager } from "../../util/UndoManager";
 
 
 interface IPageProps {
@@ -152,7 +153,6 @@ export default class Page extends React.Component<IPageProps> {
     startDrag = (e: PointerEvent): void => {
         e.preventDefault();
         e.stopPropagation();
-        console.log("dragging");
         let thisDoc = this.props.parent.Document;
         // document that this annotation is linked to
         let targetDoc = Docs.TextDocument({ width: 200, height: 200, title: "New Annotation" });
@@ -163,7 +163,7 @@ export default class Page extends React.Component<IPageProps> {
         if (this._textLayer.current) {
             DragManager.StartAnnotationDrag([this._textLayer.current], dragData, e.pageX, e.pageY, {
                 handlers: {
-                    dragComplete: action(emptyFunction),
+                    dragComplete: emptyFunction,
                 },
                 hideSource: false
             });
@@ -325,68 +325,6 @@ export default class Page extends React.Component<IPageProps> {
             PDFMenu.Instance.StartDrag = this.startDrag;
             PDFMenu.Instance.Highlight = this.highlight;
         }
-        // let x = (e.clientX - boundingRect.left) * (current.offsetWidth / boundingRect.width);
-        // let y = (e.clientY - boundingRect.top) * (current.offsetHeight / boundingRect.height);
-        // if (this._marqueeing) {
-        //     this._marqueeing = false;
-        //     if (this._marquee.current) {
-        //         let copy = document.createElement("div");
-        //         // make a copy of the marquee
-        //         copy.style.left = this._marquee.current.style.left;
-        //         copy.style.top = this._marquee.current.style.top;
-        //         copy.style.width = this._marquee.current.style.width;
-        //         copy.style.height = this._marquee.current.style.height;
-
-        //         // apply the appropriate background, opacity, and transform
-        //         let { background, opacity, transform } = this.getCurlyTransform();
-        //         copy.style.background = background;
-        //         // if curly bracing, add a curly brace
-        //         if (opacity === "1" && this._curly.current) {
-        //             copy.style.opacity = opacity;
-        //             let img = this._curly.current.cloneNode();
-        //             (img as any).style.opacity = opacity;
-        //             (img as any).style.transform = transform;
-        //             copy.appendChild(img);
-        //         }
-        //         else {
-        //             copy.style.opacity = this._marquee.current.style.opacity;
-        //         }
-        //         copy.className = this._marquee.current.className;
-        //         this.props.createAnnotation(copy, this.props.page);
-        //         this._marquee.current.style.opacity = "0";
-        //     }
-
-        //     this._marqueeHeight = this._marqueeWidth = 0;
-        // }
-        // else {
-        //     let sel = window.getSelection();
-        //     // if selecting over a range of things
-        //     if (sel && sel.type === "Range") {
-        //         let clientRects = sel.getRangeAt(0).getClientRects();
-        //         if (this._textLayer.current) {
-        //             let boundingRect = this._textLayer.current.getBoundingClientRect();
-        //             for (let i = 0; i < clientRects.length; i++) {
-        //                 let rect = clientRects.item(i);
-        //                 if (rect) {
-        //                     let annoBox = document.createElement("div");
-        //                     annoBox.className = "pdfViewer-annotationBox";
-        //                     // transforms the positions from screen onto the pdf div
-        //                     annoBox.style.top = ((rect.top - boundingRect.top) * (this._textLayer.current.offsetHeight / boundingRect.height)).toString();
-        //                     annoBox.style.left = ((rect.left - boundingRect.left) * (this._textLayer.current.offsetWidth / boundingRect.width)).toString();
-        //                     annoBox.style.width = (rect.width * this._textLayer.current.offsetWidth / boundingRect.width).toString();
-        //                     annoBox.style.height = (rect.height * this._textLayer.current.offsetHeight / boundingRect.height).toString();
-        //                     this.props.createAnnotation(annoBox, this.props.page);
-        //                 }
-        //             }
-        //         }
-        //         // clear selection
-        //         if (sel.empty) {  // Chrome
-        //             sel.empty();
-        //         } else if (sel.removeAllRanges) {  // Firefox
-        //             sel.removeAllRanges();
-        //         }
-        //     }
-        // }
         document.removeEventListener("pointermove", this.onSelectStart);
         document.removeEventListener("pointerup", this.onSelectEnd);
     }
@@ -399,7 +337,6 @@ export default class Page extends React.Component<IPageProps> {
             for (let i = 0; i < clientRects.length; i++) {
                 let rect = clientRects.item(i);
                 if (rect && rect.width !== this._textLayer.current.getBoundingClientRect().width && rect.height !== this._textLayer.current.getBoundingClientRect().height) {
-                    console.log(rect);
                     let annoBox = document.createElement("div");
                     annoBox.className = "pdfViewer-annotationBox";
                     // transforms the positions from screen onto the pdf div
-- 
cgit v1.2.3-70-g09d2


From 46d57bc21cda4703855b85a4603bd471975d845b Mon Sep 17 00:00:00 2001
From: yipstanley <stanley_yip@brown.edu>
Date: Wed, 19 Jun 2019 14:25:47 -0400
Subject: deleting annotations

---
 src/client/views/pdf/PDFMenu.tsx   | 40 +++++++++++++++++----
 src/client/views/pdf/PDFViewer.tsx | 74 ++++++++++++++++++++++++++++++++------
 src/client/views/pdf/Page.tsx      |  1 +
 3 files changed, 97 insertions(+), 18 deletions(-)

(limited to 'src/client/views/pdf/Page.tsx')

diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx
index 2462a5f94..5dd7b4bcd 100644
--- a/src/client/views/pdf/PDFMenu.tsx
+++ b/src/client/views/pdf/PDFMenu.tsx
@@ -19,9 +19,11 @@ export default class PDFMenu extends React.Component {
 
     StartDrag: (e: PointerEvent) => void = emptyFunction;
     Highlight: (d: Doc | undefined, color: string | undefined) => void = emptyFunction;
-    @observable Highlighting: boolean = false;
+    Delete: () => void = emptyFunction;
+
+    @observable public Highlighting: boolean = false;
+    @observable public Status: "pdf" | "annotation" | "" = "";
 
-    private _timeout: NodeJS.Timeout | undefined;
     private _offsetY: number = 0;
     private _offsetX: number = 0;
     private _mainCont: React.RefObject<HTMLDivElement>;
@@ -66,8 +68,8 @@ export default class PDFMenu extends React.Component {
     }
 
     @action
-    jumpTo = (x: number, y: number) => {
-        if (!this._pinned) {
+    jumpTo = (x: number, y: number, forceJump: boolean = false) => {
+        if (!this._pinned || forceJump) {
             this._transition = this._transitionDelay = "";
             this._opacity = 1;
             this._left = x;
@@ -159,11 +161,35 @@ export default class PDFMenu extends React.Component {
         }
     }
 
+    deleteClicked = (e: React.PointerEvent) => {
+        this.Delete();
+    }
+
+    handleContextMenu = (e: React.MouseEvent) => {
+        e.stopPropagation();
+        e.preventDefault();
+    }
+
     render() {
+        let buttons = this.Status === "pdf" ? [
+            <button className="pdfMenu-button" title="Click to Highlight" onClick={this.highlightClicked}
+                style={this.Highlighting ? { backgroundColor: "#121212" } : {}}>
+                <FontAwesomeIcon icon="highlighter" size="lg" style={{ transition: "transform 0.1s", transform: this.Highlighting ? "" : "rotate(-45deg)" }} />
+            </button>,
+            <button className="pdfMenu-button" title="Drag to Annotate" onPointerDown={this.pointerDown}><FontAwesomeIcon icon="comment-alt" size="lg" /></button>,
+            <button className="pdfMenu-button" title="Pin Menu" onClick={this.togglePin}
+                style={this._pinned ? { backgroundColor: "#121212" } : {}}>
+                <FontAwesomeIcon icon="thumbtack" size="lg" style={{ transition: "transform 0.1s", transform: this._pinned ? "rotate(45deg)" : "" }} />
+            </button>
+        ] : [
+                <button className="pdfMenu-button" title="Delete Anchor" onPointerDown={this.deleteClicked}><FontAwesomeIcon icon="trash-alt" size="lg" /></button>
+            ];
+
         return (
-            <div className="pdfMenu-cont" onPointerLeave={this.pointerLeave} onPointerEnter={this.pointerEntered} ref={this._mainCont}
+            <div className="pdfMenu-cont" onPointerLeave={this.pointerLeave} onPointerEnter={this.pointerEntered} ref={this._mainCont} onContextMenu={this.handleContextMenu}
                 style={{ left: this._left, top: this._top, opacity: this._opacity, transition: this._transition, transitionDelay: this._transitionDelay }}>
-                <button className="pdfMenu-button" title="Highlight" onClick={this.highlightClicked}
+                {buttons}
+                {/* <button className="pdfMenu-button" title="Highlight" onClick={this.highlightClicked}
                     style={this.Highlighting ? { backgroundColor: "#121212" } : {}}>
                     <FontAwesomeIcon icon="highlighter" size="lg" style={{ transition: "transform 0.1s", transform: this.Highlighting ? "" : "rotate(-45deg)" }} />
                 </button>
@@ -171,7 +197,7 @@ export default class PDFMenu extends React.Component {
                 <button className="pdfMenu-button" title="Pin Menu" onClick={this.togglePin}
                     style={this._pinned ? { backgroundColor: "#121212" } : {}}>
                     <FontAwesomeIcon icon="thumbtack" size="lg" style={{ transition: "transform 0.1s", transform: this._pinned ? "rotate(45deg)" : "" }} />
-                </button>
+                </button> */}
                 <div className="pdfMenu-dragger" onPointerDown={this.dragStart} style={{ width: this._pinned ? "20px" : "0px" }} />
             </div >
         );
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index f0e55705d..ea4c0bca2 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -7,7 +7,7 @@ import { Dictionary } from "typescript-collections";
 import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../new_fields/Doc";
 import { Id } from "../../../new_fields/FieldSymbols";
 import { List } from "../../../new_fields/List";
-import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types";
+import { BoolCast, Cast, NumCast, StrCast, FieldValue } from "../../../new_fields/Types";
 import { emptyFunction } from "../../../Utils";
 import { DocServer } from "../../DocServer";
 import { Docs, DocUtils } from "../../documents/Documents";
@@ -138,6 +138,7 @@ class Viewer extends React.Component<IViewerProps> {
 
     makeAnnotationDocument = (sourceDoc: Doc | undefined, s: number, color: string): Doc => {
         let annoDocs: Doc[] = [];
+        let mainAnnoDoc = new Doc();
         this._savedAnnotations.forEach((key: number, value: HTMLDivElement[]) => {
             for (let anno of value) {
                 let annoDoc = new Doc();
@@ -147,6 +148,7 @@ class Viewer extends React.Component<IViewerProps> {
                 if (anno.style.width) annoDoc.width = parseInt(anno.style.width) / scale;
                 annoDoc.page = key;
                 annoDoc.target = sourceDoc;
+                annoDoc.group = mainAnnoDoc;
                 annoDoc.color = color;
                 annoDoc.type = AnnotationTypes.Region;
                 annoDocs.push(annoDoc);
@@ -154,13 +156,12 @@ class Viewer extends React.Component<IViewerProps> {
             }
         });
 
-        let annoDoc = new Doc();
-        annoDoc.annotations = new List<Doc>(annoDocs);
+        mainAnnoDoc.annotations = new List<Doc>(annoDocs);
         if (sourceDoc) {
-            DocUtils.MakeLink(sourceDoc, annoDoc, undefined, `Annotation from ${StrCast(this.props.parent.Document.title)}`, "", StrCast(this.props.parent.Document.title));
+            DocUtils.MakeLink(sourceDoc, mainAnnoDoc, undefined, `Annotation from ${StrCast(this.props.parent.Document.title)}`, "", StrCast(this.props.parent.Document.title));
         }
         this._savedAnnotations.clear();
-        return annoDoc;
+        return mainAnnoDoc;
     }
 
     drop = async (e: Event, de: DragManager.DropEvent) => {
@@ -508,6 +509,57 @@ interface IAnnotationProps {
 class RegionAnnotation extends React.Component<IAnnotationProps> {
     @observable private _backgroundColor: string = "red";
 
+    private _reactionDisposer?: IReactionDisposer;
+    private _mainCont: React.RefObject<HTMLDivElement>;
+
+    constructor(props: IAnnotationProps) {
+        super(props);
+
+        this._mainCont = React.createRef();
+    }
+
+    componentDidMount() {
+        this._reactionDisposer = reaction(
+            () => BoolCast(this.props.document.delete),
+            () => {
+                if (BoolCast(this.props.document.delete)) {
+                    if (this._mainCont.current) {
+                        this._mainCont.current.style.display = "none";
+                    }
+                }
+            },
+            { fireImmediately: true }
+        );
+    }
+
+    componentWillUnmount() {
+        this._reactionDisposer && this._reactionDisposer();
+    }
+
+    deleteAnnotation = () => {
+        let annotation = DocListCast(this.props.parent.props.parent.Document.annotations);
+        let group = FieldValue(Cast(this.props.document.group, Doc));
+        if (group && annotation.indexOf(group) !== -1) {
+            let newAnnotations = annotation.filter(a => a !== FieldValue(Cast(this.props.document.group, Doc)));
+            this.props.parent.props.parent.Document.annotations = new List<Doc>(newAnnotations);
+        }
+
+        if (group) {
+            let groupAnnotations = DocListCast(group.annotations);
+            groupAnnotations.forEach(anno => anno.delete = true);
+        }
+    }
+
+
+    // annotateThis = (e: PointerEvent) => {
+    //     e.preventDefault();
+    //     e.stopPropagation();
+    //     // document that this annotation is linked to
+    //     let targetDoc = Docs.TextDocument({ width: 200, height: 200, title: "New Annotation" });
+    //     let group = FieldValue(Cast(this.props.document.group, Doc));
+    // }
+
+    @action
     onPointerDown = (e: React.PointerEvent) => {
         if (e.button === 0) {
             let targetDoc = Cast(this.props.document.target, Doc, null);
@@ -515,16 +567,16 @@ class RegionAnnotation extends React.Component<IAnnotationProps> {
                 DocumentManager.Instance.jumpToDocument(targetDoc);
             }
         }
-        // if (e.button === 2) {
-        //     console.log("right");
-        //     e.stopPropagation();
-        //     e.preventDefault();
-        // }
+        if (e.button === 2) {
+            PDFMenu.Instance.Status = "annotation";
+            PDFMenu.Instance.Delete = this.deleteAnnotation;
+            PDFMenu.Instance.jumpTo(e.clientX, e.clientY, true);
+        }
     }
 
     render() {
         return (
-            <div className="pdfViewer-annotationBox" onPointerDown={this.onPointerDown}
+            <div className="pdfViewer-annotationBox" onPointerDown={this.onPointerDown} ref={this._mainCont}
                 style={{ top: this.props.y * scale, left: this.props.x * scale, width: this.props.width * scale, height: this.props.height * scale, pointerEvents: "all", backgroundColor: StrCast(this.props.document.color) }}></div>
         );
     }
diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx
index 39e737c32..734dff7fc 100644
--- a/src/client/views/pdf/Page.tsx
+++ b/src/client/views/pdf/Page.tsx
@@ -191,6 +191,7 @@ export default class Page extends React.Component<IPageProps> {
         else if (e.button === 0) {
             PDFMenu.Instance.StartDrag = this.startDrag;
             PDFMenu.Instance.Highlight = this.highlight;
+            PDFMenu.Instance.Status = "pdf";
             PDFMenu.Instance.fadeOut(true);
             let target: any = e.target;
             if (target && target.parentElement === this._textLayer.current) {
-- 
cgit v1.2.3-70-g09d2


From d2dfc0f9d35f0084a7c0dea73215f5d21055f2f3 Mon Sep 17 00:00:00 2001
From: yipstanley <stanley_yip@brown.edu>
Date: Thu, 20 Jun 2019 17:17:14 -0400
Subject: pdf page sizes loading error

---
 src/client/views/pdf/PDFViewer.tsx | 1 +
 src/client/views/pdf/Page.tsx      | 5 +++--
 2 files changed, 4 insertions(+), 2 deletions(-)

(limited to 'src/client/views/pdf/Page.tsx')

diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 7000352e7..6adead626 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -203,6 +203,7 @@ class Viewer extends React.Component<IViewerProps> {
             this._isPage[page] = "page";
             this._visibleElements[page] = (
                 <Page
+                    size={this._pageSizes[page]}
                     pdf={this.props.pdf}
                     page={page}
                     numPages={this.props.pdf.numPages}
diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx
index 734dff7fc..b6f362702 100644
--- a/src/client/views/pdf/Page.tsx
+++ b/src/client/views/pdf/Page.tsx
@@ -19,6 +19,7 @@ import { UndoManager } from "../../util/UndoManager";
 
 
 interface IPageProps {
+    size: { width: number, height: number };
     pdf: Opt<Pdfjs.PDFDocumentProxy>;
     name: string;
     numPages: number;
@@ -36,8 +37,8 @@ interface IPageProps {
 @observer
 export default class Page extends React.Component<IPageProps> {
     @observable private _state: string = "N/A";
-    @observable private _width: number = 0;
-    @observable private _height: number = 0;
+    @observable private _width: number = this.props.size.width;
+    @observable private _height: number = this.props.size.height;
     @observable private _page: Opt<Pdfjs.PDFPageProxy>;
     @observable private _currPage: number = this.props.page + 1;
     @observable private _marqueeX: number = 0;
-- 
cgit v1.2.3-70-g09d2

