aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/pdf
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/pdf')
-rw-r--r--src/client/views/pdf/Annotation.tsx15
-rw-r--r--src/client/views/pdf/PDFMenu.tsx24
-rw-r--r--src/client/views/pdf/PDFViewer.tsx29
-rw-r--r--src/client/views/pdf/Page.tsx96
4 files changed, 91 insertions, 73 deletions
diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx
index 73fca229b..0a1661a1a 100644
--- a/src/client/views/pdf/Annotation.tsx
+++ b/src/client/views/pdf/Annotation.tsx
@@ -8,6 +8,7 @@ import { Id } from "../../../new_fields/FieldSymbols";
import { List } from "../../../new_fields/List";
import PDFMenu from "./PDFMenu";
import { DocumentManager } from "../../util/DocumentManager";
+import { PresentationView } from "../presentationview/PresentationView";
interface IAnnotationProps {
anno: Doc;
@@ -74,7 +75,7 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
() => this.props.parent.Index,
() => {
if (this.props.parent.Index === this.props.index) {
- this.props.parent.scrollTo(this.props.y - 50);
+ this.props.parent.scrollTo(this.props.y * scale - (NumCast(this.props.parent.props.parent.Document.pdfHeight) / 2));
}
}
);
@@ -101,12 +102,19 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
PDFMenu.Instance.fadeOut(true);
}
+ pinToPres = () => {
+ let group = FieldValue(Cast(this.props.document.group, Doc));
+ if (group) {
+ PresentationView.Instance.PinDoc(group);
+ }
+ }
+
@action
onPointerDown = (e: React.PointerEvent) => {
if (e.button === 0) {
let targetDoc = Cast(this.props.document.target, Doc, null);
if (targetDoc) {
- DocumentManager.Instance.jumpToDocument(targetDoc, true);
+ DocumentManager.Instance.jumpToDocument(targetDoc, false);
}
}
if (e.button === 2) {
@@ -114,6 +122,7 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
PDFMenu.Instance.Delete = this.deleteAnnotation.bind(this);
PDFMenu.Instance.Pinned = false;
PDFMenu.Instance.AddTag = this.addTag.bind(this);
+ PDFMenu.Instance.PinToPres = this.pinToPres;
PDFMenu.Instance.jumpTo(e.clientX, e.clientY, true);
}
}
@@ -137,7 +146,7 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
width: this.props.width * scale,
height: this.props.height * scale,
pointerEvents: "all",
- backgroundColor: this.props.parent.Index === this.props.index ? "goldenrod" : StrCast(this.props.document.color)
+ backgroundColor: this.props.parent.Index === this.props.index ? "green" : StrCast(this.props.document.color)
}}></div>
);
}
diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx
index aeed5213c..d6970e7f4 100644
--- a/src/client/views/pdf/PDFMenu.tsx
+++ b/src/client/views/pdf/PDFMenu.tsx
@@ -3,10 +3,8 @@ import "./PDFMenu.scss";
import { observable, action, runInAction } from "mobx";
import { observer } from "mobx-react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { emptyFunction, returnZero, returnTrue, returnFalse } from "../../../Utils";
+import { emptyFunction, returnFalse } from "../../../Utils";
import { Doc } from "../../../new_fields/Doc";
-import { DragManager } from "../../util/DragManager";
-import { DocUtils } from "../../documents/Documents";
@observer
export default class PDFMenu extends React.Component {
@@ -19,11 +17,12 @@ export default class PDFMenu extends React.Component {
@observable private _transitionDelay: string = "";
- StartDrag: (e: PointerEvent) => void = emptyFunction;
+ StartDrag: (e: PointerEvent, ele: HTMLDivElement) => void = emptyFunction;
Highlight: (d: Doc | undefined, color: string | undefined) => void = emptyFunction;
Delete: () => void = emptyFunction;
Snippet: (marquee: { left: number, top: number, width: number, height: number }) => void = emptyFunction;
AddTag: (key: string, value: string) => boolean = returnFalse;
+ PinToPres: () => void = emptyFunction;
@observable public Highlighting: boolean = false;
@observable public Status: "pdf" | "annotation" | "snippet" | "" = "";
@@ -33,9 +32,10 @@ export default class PDFMenu extends React.Component {
private _offsetY: number = 0;
private _offsetX: number = 0;
- private _mainCont: React.RefObject<HTMLDivElement>;
+ private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
+ private _commentCont: React.RefObject<HTMLDivElement> = React.createRef();
+ private _snippetButton: React.RefObject<HTMLButtonElement> = React.createRef();
private _dragging: boolean = false;
- private _snippetButton: React.RefObject<HTMLButtonElement>;
@observable private _keyValue: string = "";
@observable private _valueValue: string = "";
@observable private _added: boolean = false;
@@ -44,9 +44,6 @@ export default class PDFMenu extends React.Component {
super(props);
PDFMenu.Instance = this;
-
- this._mainCont = React.createRef();
- this._snippetButton = React.createRef();
}
pointerDown = (e: React.PointerEvent) => {
@@ -67,7 +64,7 @@ export default class PDFMenu extends React.Component {
return;
}
- this.StartDrag(e);
+ this.StartDrag(e, this._commentCont.current!);
this._dragging = true;
}
@@ -244,7 +241,7 @@ export default class PDFMenu extends React.Component {
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" key="2" /></button>,
+ <button className="pdfMenu-button" title="Drag to Annotate" ref={this._commentCont} onPointerDown={this.pointerDown}><FontAwesomeIcon icon="comment-alt" size="lg" key="2" /></button>,
this.Status === "snippet" ? <button className="pdfMenu-button" title="Drag to Snippetize Selection" onPointerDown={this.snippetStart} ref={this._snippetButton}><FontAwesomeIcon icon="cut" size="lg" /></button> : undefined,
<button className="pdfMenu-button" title="Pin Menu" onClick={this.togglePin} key="3"
style={this.Pinned ? { backgroundColor: "#121212" } : {}}>
@@ -252,11 +249,12 @@ export default class PDFMenu extends React.Component {
</button>
] : [
<button className="pdfMenu-button" title="Delete Anchor" onPointerDown={this.deleteClicked}><FontAwesomeIcon icon="trash-alt" size="lg" key="1" /></button>,
- <div className="pdfMenu-addTag" key="2">
+ <button className="pdfMenu-button" title="Pin to Presentation" onPointerDown={this.PinToPres}><FontAwesomeIcon icon="map-pin" size="lg" key="2" /></button>,
+ <div className="pdfMenu-addTag" key="3">
<input onChange={this.keyChanged} placeholder="Key" style={{ gridColumn: 1 }} />
<input onChange={this.valueChanged} placeholder="Value" style={{ gridColumn: 3 }} />
</div>,
- <button className="pdfMenu-button" title={`Add tag: ${this._keyValue} with value: ${this._valueValue}`} onPointerDown={this.addTag}><FontAwesomeIcon style={{ transition: "all .2s" }} color={this._added ? "#42f560" : "white"} icon="check" size="lg" key="3" /></button>,
+ <button className="pdfMenu-button" title={`Add tag: ${this._keyValue} with value: ${this._valueValue}`} onPointerDown={this.addTag}><FontAwesomeIcon style={{ transition: "all .2s" }} color={this._added ? "#42f560" : "white"} icon="check" size="lg" key="4" /></button>,
];
return (
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index bb148e738..8af29110f 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -166,6 +166,7 @@ export class Viewer extends React.Component<IViewerProps> {
}
});
}
+ this.Index = -1;
});
}
);
@@ -234,11 +235,15 @@ export class Viewer extends React.Component<IViewerProps> {
mainAnnoDoc.title = "Annotation on " + StrCast(this.props.parent.Document.title);
mainAnnoDoc.pdfDoc = this.props.parent.Document;
+ let minY = Number.MAX_VALUE;
this._savedAnnotations.forEach((key: number, value: HTMLDivElement[]) => {
for (let anno of value) {
let annoDoc = new Doc();
if (anno.style.left) annoDoc.x = parseInt(anno.style.left) / scale;
- if (anno.style.top) annoDoc.y = parseInt(anno.style.top) / scale;
+ if (anno.style.top) {
+ annoDoc.y = parseInt(anno.style.top) / scale;
+ minY = Math.min(parseInt(anno.style.top), minY);
+ }
if (anno.style.height) annoDoc.height = parseInt(anno.style.height) / scale;
if (anno.style.width) annoDoc.width = parseInt(anno.style.width) / scale;
annoDoc.page = key;
@@ -251,12 +256,13 @@ export class Viewer extends React.Component<IViewerProps> {
}
});
- mainAnnoDoc.y = Math.max((NumCast(annoDocs[0].y) * scale) - 100, 0);
+ mainAnnoDoc.y = Math.max(minY, 0);
mainAnnoDoc.annotations = new List<Doc>(annoDocs);
if (sourceDoc) {
DocUtils.MakeLink(sourceDoc, mainAnnoDoc, undefined, `Annotation from ${StrCast(this.props.parent.Document.title)}`, "", StrCast(this.props.parent.Document.title));
}
this._savedAnnotations.clear();
+ this.Index = -1;
return mainAnnoDoc;
}
@@ -426,7 +432,7 @@ export class Viewer extends React.Component<IViewerProps> {
}
renderAnnotation = (anno: Doc, index: number): JSX.Element => {
- return <Annotation anno={anno} index={index} parent={this} />;
+ return <Annotation anno={anno} index={index} parent={this} key={`${anno[Id]}-annotation`} />;
}
@action
@@ -562,9 +568,10 @@ export class Viewer extends React.Component<IViewerProps> {
prevAnnotation = (e: React.MouseEvent) => {
e.stopPropagation();
- if (this.Index > 0) {
- this.Index--;
- }
+ // if (this.Index > 0) {
+ // this.Index--;
+ // }
+ this.Index = Math.max(this.Index - 1, 0);
}
@action
@@ -572,7 +579,7 @@ export class Viewer extends React.Component<IViewerProps> {
e.stopPropagation();
let compiled = this._script;
- if (this.Index < this._annotations.filter(anno => {
+ let filtered = this._annotations.filter(anno => {
if (compiled && compiled.compiled) {
let run = compiled.run({ this: anno });
if (run.success) {
@@ -580,9 +587,8 @@ export class Viewer extends React.Component<IViewerProps> {
}
}
return true;
- }).length) {
- this.Index++;
- }
+ });
+ this.Index = Math.min(this.Index + 1, filtered.length - 1)
}
nextResult = () => {
@@ -630,7 +636,8 @@ export class Viewer extends React.Component<IViewerProps> {
}
}
return true;
- }).map((anno: Doc, index: number) => this.renderAnnotation(anno, index))}
+ }).sort((a: Doc, b: Doc) => NumCast(a.y) - NumCast(b.y))
+ .map((anno: Doc, index: number) => this.renderAnnotation(anno, index))}
</div>
</div>
<div className="pdfViewer-overlayCont" onPointerDown={(e) => e.stopPropagation()}
diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx
index 57e36be43..49eac71c4 100644
--- a/src/client/views/pdf/Page.tsx
+++ b/src/client/views/pdf/Page.tsx
@@ -52,7 +52,7 @@ export default class Page extends React.Component<IPageProps> {
private _textLayer: React.RefObject<HTMLDivElement>;
private _annotationLayer: React.RefObject<HTMLDivElement>;
private _marquee: React.RefObject<HTMLDivElement>;
- private _curly: React.RefObject<HTMLImageElement>;
+ // private _curly: React.RefObject<HTMLImageElement>;
private _marqueeing: boolean = false;
private _reactionDisposer?: IReactionDisposer;
@@ -62,7 +62,7 @@ export default class Page extends React.Component<IPageProps> {
this._textLayer = React.createRef();
this._annotationLayer = React.createRef();
this._marquee = React.createRef();
- this._curly = React.createRef();
+ // this._curly = React.createRef();
}
componentDidMount = (): void => {
@@ -152,7 +152,7 @@ export default class Page extends React.Component<IPageProps> {
* start a drag event and create or put the necessary info into the drag event.
*/
@action
- startDrag = (e: PointerEvent): void => {
+ startDrag = (e: PointerEvent, ele: HTMLDivElement): void => {
e.preventDefault();
e.stopPropagation();
let thisDoc = this.props.parent.Document;
@@ -163,7 +163,7 @@ export default class Page extends React.Component<IPageProps> {
// create dragData and star tdrag
let dragData = new DragManager.AnnotationDragData(thisDoc, annotationDoc, targetDoc);
if (this._textLayer.current) {
- DragManager.StartAnnotationDrag([this._textLayer.current], dragData, e.pageX, e.pageY, {
+ DragManager.StartAnnotationDrag([ele], dragData, e.pageX, e.pageY, {
handlers: {
dragComplete: emptyFunction,
},
@@ -183,8 +183,11 @@ export default class Page extends React.Component<IPageProps> {
let doc = this.props.parent.Document;
let view = Doc.MakeAlias(doc);
let data = Doc.MakeDelegate(doc.proto!);
+ data.title = StrCast(data.title) + "_snippet";
view.proto = data;
view.nativeHeight = marquee.height;
+ view.height = (doc[WidthSym]() / NumCast(doc.nativeWidth)) * marquee.height;
+ view.nativeWidth = doc.nativeWidth;
view.startY = marquee.top + this.props.getScrollFromPage(this.props.page);
view.width = doc[WidthSym]();
let dragData = new DragManager.DocumentDragData([view], [undefined]);
@@ -244,9 +247,9 @@ export default class Page extends React.Component<IPageProps> {
this._marqueeWidth = (e.clientX - boundingRect.left) * (current.offsetWidth / boundingRect.width) - this._marqueeX;
this._marqueeHeight = (e.clientY - boundingRect.top) * (current.offsetHeight / boundingRect.height) - this._marqueeY;
let { background, opacity, transform: transform } = this.getCurlyTransform();
- if (this._marquee.current && this._curly.current) {
+ if (this._marquee.current /*&& this._curly.current*/) {
this._marquee.current.style.background = background;
- this._curly.current.style.opacity = opacity;
+ // this._curly.current.style.opacity = opacity;
this._rotate = transform;
}
}
@@ -259,33 +262,33 @@ export default class Page extends React.Component<IPageProps> {
}
getCurlyTransform = (): { background: string, opacity: string, transform: string } => {
- let background = "", opacity = "", transform = "";
- if (this._marquee.current && this._curly.current) {
- if (this._marqueeWidth > 100 && this._marqueeHeight > 100) {
- background = "red";
- opacity = "0";
- }
- else {
- background = "transparent";
- opacity = "1";
- }
-
- // split up for simplicity, could be done in a nested ternary. please do not. -syip2
- let ratio = this._marqueeWidth / this._marqueeHeight;
- if (ratio > 1.5) {
- // vertical
- transform = "rotate(90deg) scale(1, 5)";
- }
- else if (ratio < 0.5) {
- // horizontal
- transform = "scale(2, 1)";
- }
- else {
- // diagonal
- transform = "rotate(45deg) scale(1.5, 1.5)";
- }
- }
- return { background: background, opacity: opacity, transform: transform };
+ // let background = "", opacity = "", transform = "";
+ // if (this._marquee.current && this._curly.current) {
+ // if (this._marqueeWidth > 100 && this._marqueeHeight > 100) {
+ // background = "red";
+ // opacity = "0";
+ // }
+ // else {
+ // background = "transparent";
+ // opacity = "1";
+ // }
+
+ // // split up for simplicity, could be done in a nested ternary. please do not. -syip2
+ // let ratio = this._marqueeWidth / this._marqueeHeight;
+ // if (ratio > 1.5) {
+ // // vertical
+ // transform = "rotate(90deg) scale(1, 5)";
+ // }
+ // else if (ratio < 0.5) {
+ // // horizontal
+ // transform = "scale(2, 1)";
+ // }
+ // else {
+ // // diagonal
+ // transform = "rotate(45deg) scale(1.5, 1.5)";
+ // }
+ // }
+ return { background: "red", opacity: "0.5", transform: "" };
}
@action
@@ -305,16 +308,17 @@ export default class Page extends React.Component<IPageProps> {
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 = style.opacity;
- }
+ // 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.border = style.border;
+ copy.style.opacity = style.opacity;
+ // }
copy.className = this._marquee.current.className;
this.props.createAnnotation(copy, this.props.page);
this._marquee.current.style.opacity = "0";
@@ -340,7 +344,7 @@ export default class Page extends React.Component<IPageProps> {
if (PDFMenu.Instance.Highlighting) {
- this.highlight(undefined, "#f4f442");
+ this.highlight(undefined, "goldenrod");
}
else {
PDFMenu.Instance.StartDrag = this.startDrag;
@@ -401,8 +405,8 @@ export default class Page extends React.Component<IPageProps> {
</div>
<div className="pdfInkingLayer-cont" ref={this._annotationLayer} style={{ width: "100%", height: "100%", position: "relative", top: "-100%" }}>
<div className="pdfViewer-annotationBox" ref={this._marquee}
- style={{ left: `${this._marqueeX}px`, top: `${this._marqueeY}px`, width: `${this._marqueeWidth}px`, height: `${this._marqueeHeight}px`, background: "transparent" }}>
- <img ref={this._curly} src="https://static.thenounproject.com/png/331760-200.png" style={{ width: "100%", height: "100%", transform: `${this._rotate}` }} />
+ style={{ left: `${this._marqueeX}px`, top: `${this._marqueeY}px`, width: `${this._marqueeWidth}px`, height: `${this._marqueeHeight}px`, background: "red", border: `${this._marqueeWidth === 0 ? "" : "10px dashed black"}` }}>
+ {/* <img ref={this._curly} src="https://static.thenounproject.com/png/331760-200.png" style={{ width: "100%", height: "100%", transform: `${this._rotate}` }} /> */}
</div>
</div>
<div className="textlayer" ref={this._textLayer} style={{ "position": "relative", "top": `-${2 * this._height}px`, "height": `${this._height}px` }} />