aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryipstanley <stanley_yip@brown.edu>2019-05-19 19:10:44 -0400
committeryipstanley <stanley_yip@brown.edu>2019-05-19 19:10:44 -0400
commit3a9f1a40cb6bcd35783aa83e66c3e253812aa39d (patch)
treea467f21d2c357df517fd5ec6b5b85096809b255b
parenteec769b586d4a1c6e73c4ce4ae78b4b8f2d4762b (diff)
stacking !
-rw-r--r--src/client/documents/Documents.ts7
-rw-r--r--src/client/views/nodes/PDFBox.tsx296
-rw-r--r--src/client/views/pdf/PDFViewer.tsx31
3 files changed, 21 insertions, 313 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 5752bb096..2df733fd5 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -33,12 +33,9 @@ import { DocServer } from "../DocServer";
import { StrokeData, InkField } from "../../new_fields/InkField";
import { dropActionType } from "../util/DragManager";
import { DateField } from "../../new_fields/DateField";
-<<<<<<< HEAD
import { PDFBox2 } from "../views/pdf/PDFBox2";
-=======
import { schema } from "prosemirror-schema-basic";
import { UndoManager } from "../util/UndoManager";
->>>>>>> 01a223f2e6685506cc1e5db69e9062d5ff0d3246
export interface DocumentOptions {
x?: number;
@@ -173,8 +170,8 @@ export namespace Docs {
return textProto;
}
function CreatePdfPrototype(): Doc {
- let pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionPDFView.LayoutString("annotations"),
- { x: 0, y: 0, nativeWidth: 1200, width: 300, height: 300, backgroundLayout: PDFBox.LayoutString(), curPage: 1 });
+ let pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", PDFBox.LayoutString(),
+ { x: 0, y: 0, width: 300, height: 300, backgroundLayout: PDFBox.LayoutString(), curPage: 1 });
return pdfProto;
}
function CreateWebPrototype(): Doc {
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 9b0207d0c..d74dc53c4 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -4,8 +4,8 @@ import { observer } from "mobx-react";
import 'react-image-lightbox/style.css';
import Measure from "react-measure";
//@ts-ignore
-import { Document, Page } from "react-pdf";
-import 'react-pdf/dist/Page/AnnotationLayer.css';
+// import { Document, Page } from "react-pdf";
+// import 'react-pdf/dist/Page/AnnotationLayer.css';
import { RouteStore } from "../../../server/RouteStore";
import { Utils } from '../../../Utils';
import { Annotation } from './Annotation';
@@ -14,7 +14,7 @@ import "./PDFBox.scss";
import React = require("react");
import { SelectionManager } from "../../util/SelectionManager";
import { Cast, FieldValue, NumCast } from "../../../new_fields/Types";
-import { Opt } from "../../../new_fields/Doc";
+import { Opt, HeightSym, Doc } from "../../../new_fields/Doc";
import { DocComponent } from "../DocComponent";
import { makeInterface } from "../../../new_fields/Schema";
import { positionSchema } from "./DocumentView";
@@ -53,300 +53,26 @@ const PdfDocument = makeInterface(positionSchema, pageSchema);
export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocument) {
public static LayoutString() { return FieldView.LayoutString(PDFBox); }
- private _mainDiv = React.createRef<HTMLDivElement>();
- private renderHeight = 2400;
-
- @observable private _renderAsSvg = true;
@observable private _alt = false;
-
- private _reactionDisposer?: IReactionDisposer;
-
- @observable private _perPageInfo: Object[] = []; //stores pageInfo
- @observable private _pageInfo: any = { area: [], divs: [], anno: [] }; //divs is array of objects linked to anno
-
- @observable private _currAnno: any = [];
@observable private _interactive: boolean = false;
- @observable private _loaded: boolean = false;
-
- @computed private get curPage() { return NumCast(this.Document.curPage, 1); }
- @computed private get thumbnailPage() { return NumCast(this.props.Document.thumbnailPage, -1); }
-
- componentDidMount() {
- let wasSelected = false;
- this._reactionDisposer = reaction(
- () => this.props.isSelected(),
- () => {
- if (this.curPage > 0 && this.curPage !== this.thumbnailPage && wasSelected && !this.props.isSelected()) {
- this.saveThumbnail();
- }
- wasSelected = this._interactive = this.props.isSelected();
- },
- { fireImmediately: true });
-
- }
-
- componentWillUnmount() {
- if (this._reactionDisposer) this._reactionDisposer();
- }
-
- /**
- * highlighting helper function
- */
- makeEditableAndHighlight = (colour: string) => {
- var range, sel = window.getSelection();
- if (sel && sel.rangeCount && sel.getRangeAt) {
- range = sel.getRangeAt(0);
- }
- document.designMode = "on";
- if (!document.execCommand("HiliteColor", false, colour)) {
- document.execCommand("HiliteColor", false, colour);
- }
-
- if (range && sel) {
- sel.removeAllRanges();
- sel.addRange(range);
-
- let obj: Object = { parentDivs: [], spans: [] };
- //@ts-ignore
- if (range.commonAncestorContainer.className === 'react-pdf__Page__textContent') { //multiline highlighting case
- obj = this.highlightNodes(range.commonAncestorContainer.childNodes);
- } else { //single line highlighting case
- let parentDiv = range.commonAncestorContainer.parentElement;
- if (parentDiv) {
- if (parentDiv.className === 'react-pdf__Page__textContent') { //when highlight is overwritten
- obj = this.highlightNodes(parentDiv.childNodes);
- } else {
- parentDiv.childNodes.forEach((child) => {
- if (child.nodeName === 'SPAN') {
- //@ts-ignore
- obj.parentDivs.push(parentDiv);
- //@ts-ignore
- child.id = "highlighted";
- //@ts-ignore
- obj.spans.push(child);
- // child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler
- }
- });
- }
- }
- }
- this._pageInfo.divs.push(obj);
-
- }
- document.designMode = "off";
- }
-
- highlightNodes = (nodes: NodeListOf<ChildNode>) => {
- let temp = { parentDivs: [], spans: [] };
- nodes.forEach((div) => {
- div.childNodes.forEach((child) => {
- if (child.nodeName === 'SPAN') {
- //@ts-ignore
- temp.parentDivs.push(div);
- //@ts-ignore
- child.id = "highlighted";
- //@ts-ignore
- temp.spans.push(child);
- // child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler
- }
- });
-
- });
- return temp;
- }
-
- /**
- * when the cursor enters the highlight, it pops out annotation. ONLY WORKS FOR SINGLE DIV LINES
- */
- @action
- onEnter = (e: any) => {
- let span: HTMLSpanElement = e.toElement;
- let index: any;
- this._pageInfo.divs.forEach((obj: any) => {
- obj.spans.forEach((element: any) => {
- if (element === span && !index) {
- index = this._pageInfo.divs.indexOf(obj);
- }
- });
- });
-
- if (this._pageInfo.anno.length >= index + 1) {
- if (this._currAnno.length === 0) {
- this._currAnno.push(this._pageInfo.anno[index]);
- }
- } else {
- if (this._currAnno.length === 0) { //if there are no current annotation
- let div = span.offsetParent;
- //@ts-ignore
- let divX = div.style.left;
- //@ts-ignore
- let divY = div.style.top;
- //slicing "px" from the end
- divX = divX.slice(0, divX.length - 2); //gets X of the DIV element (parent of Span)
- divY = divY.slice(0, divY.length - 2); //gets Y of the DIV element (parent of Span)
- let annotation = <Annotation key={Utils.GenerateGuid()} Span={span} X={divX} Y={divY - 300} Highlights={this._pageInfo.divs} Annotations={this._pageInfo.anno} CurrAnno={this._currAnno} />;
- this._pageInfo.anno.push(annotation);
- this._currAnno.push(annotation);
- }
- }
-
- }
- /**
- * highlight function for highlighting actual text. This works fine.
- */
- highlight = (color: string) => {
- if (window.getSelection()) {
- try {
- if (!document.execCommand("hiliteColor", false, color)) {
- this.makeEditableAndHighlight(color);
- }
- } catch (ex) {
- this.makeEditableAndHighlight(color);
- }
+ getHeight = (): number => {
+ if (this.props.Document) {
+ let doc = this.props.Document.proto ? this.props.Document.proto : this.props.Document;
+ console.log(doc);
+ return NumCast(doc.height);
}
+ return 0;
}
- /**
- * controls the area highlighting (stickies) Kinda temporary
- */
- onPointerDown = (e: React.PointerEvent) => {
- if (this.props.isSelected() && !InkingControl.Instance.selectedTool && e.buttons === 1) {
- if (e.altKey) {
- this._alt = true;
- } else {
- if (e.metaKey) {
- e.stopPropagation();
- }
- }
- document.removeEventListener("pointerup", this.onPointerUp);
- document.addEventListener("pointerup", this.onPointerUp);
- }
- if (this.props.isSelected() && e.buttons === 2) {
- runInAction(() => this._alt = true);
- document.removeEventListener("pointerup", this.onPointerUp);
- document.addEventListener("pointerup", this.onPointerUp);
- }
- }
-
- /**
- * controls area highlighting and partially highlighting. Kinda temporary
- */
- @action
- onPointerUp = (e: PointerEvent) => {
- this._alt = false;
- document.removeEventListener("pointerup", this.onPointerUp);
- if (this.props.isSelected()) {
- this.highlight("rgba(76, 175, 80, 0.3)"); //highlights to this default color.
- }
- this._interactive = true;
- }
-
-
- @action
- saveThumbnail = () => {
- this._renderAsSvg = false;
- setTimeout(() => {
- let nwidth = FieldValue(this.Document.nativeWidth, 0);
- let nheight = FieldValue(this.Document.nativeHeight, 0);
- htmlToImage.toPng(this._mainDiv.current!, { width: nwidth, height: nheight, quality: 1 })
- .then(action((dataUrl: string) => {
- this.props.Document.thumbnail = new ImageField(new URL(dataUrl));
- this.props.Document.thumbnailPage = FieldValue(this.Document.curPage, -1);
- this._renderAsSvg = true;
- }))
- .catch(function (error: any) {
- console.error('oops, something went wrong!', error);
- });
- }, 1250);
- }
-
- @action
- onLoaded = (page: any) => {
- // bcz: the number of pages should really be set when the document is imported.
- this.props.Document.numPages = page._transport.numPages;
- if (this._perPageInfo.length === 0) { //Makes sure it only runs once
- this._perPageInfo = [...Array(page._transport.numPages)];
- }
- this._loaded = true;
- }
-
- @action
- setScaling = (r: any) => {
- // bcz: the nativeHeight should really be set when the document is imported.
- // also, the native dimensions could be different for different pages of the canvas
- // so this design is flawed.
- var nativeWidth = FieldValue(this.Document.nativeWidth, 0);
- if (!FieldValue(this.Document.nativeHeight, 0)) {
- var nativeHeight = nativeWidth * r.offset.height / r.offset.width;
- this.props.Document.height = nativeHeight / nativeWidth * FieldValue(this.Document.width, 0);
- this.props.Document.nativeHeight = nativeHeight;
- }
- }
- @computed
- get pdfPage() {
- return <Page height={this.renderHeight} renderTextLayer={false} pageNumber={this.curPage} onLoadSuccess={this.onLoaded} />;
- }
- @computed
- get pdfContent() {
- trace();
- let pdfUrl = Cast(this.props.Document[this.props.fieldKey], PdfField);
- if (!pdfUrl) {
- return <p>No pdf url to render</p>;
- }
- let pdfpage = this.pdfPage;
- let body = this.Document.nativeHeight ?
- pdfpage :
- <Measure offset onResize={this.setScaling}>
- {({ measureRef }) =>
- <div className="pdfBox-page" ref={measureRef}>
- {pdfpage}
- </div>
- }
- </Measure>;
- let xf = (this.Document.nativeHeight || 0) / this.renderHeight;
- return <div className="pdfBox-contentContainer" key="container" style={{ transform: `scale(${xf}, ${xf})` }}>
- <Document file={window.origin + RouteStore.corsProxy + `/${pdfUrl.url}`} renderMode={this._renderAsSvg ? "svg" : "canvas"}>
- {body}
- </Document>
- </div >;
- }
-
- @computed
- get pdfRenderer() {
- let proxy = this._loaded ? (null) : this.imageProxyRenderer;
- let pdfUrl = Cast(this.props.Document[this.props.fieldKey], PdfField);
- if ((!this._interactive && proxy) || !pdfUrl) {
- return proxy;
- }
- return [
- this._pageInfo.area.filter(() => this._pageInfo.area).map((element: any) => element),
- this._currAnno.map((element: any) => element),
- this.pdfContent,
- proxy
- ];
- }
-
- @computed
- get imageProxyRenderer() {
- let thumbField = this.props.Document.thumbnail;
- if (thumbField) {
- let path = this.thumbnailPage !== this.curPage ? "https://image.flaticon.com/icons/svg/66/66163.svg" :
- thumbField instanceof ImageField ? thumbField.url.href : "http://cs.brown.edu/people/bcz/prairie.jpg";
- return <img src={path} width="100%" />;
- }
- return (null);
- }
- @action onKeyDown = (e: React.KeyboardEvent) => e.key === "Alt" && (this._alt = true);
- @action onKeyUp = (e: React.KeyboardEvent) => e.key === "Alt" && (this._alt = false);
render() {
trace();
const pdfUrl = window.origin + RouteStore.corsProxy + "/https://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf";
let classname = "pdfBox-cont" + (this.props.isSelected() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : "");
return (
- <div className={classname} tabIndex={0} ref={this._mainDiv} onPointerDown={this.onPointerDown} onKeyDown={this.onKeyDown} onKeyUp={this.onKeyUp} >
+ <div style={{ overflow: "scroll", height: `${NumCast(this.props.Document.height)}px` }} onWheel={(e: React.WheelEvent) => e.stopPropagation()} className={classname}>
<PDFViewer url={pdfUrl} />
- </div >
+ </div>
);
}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 1b445eae4..26becebf1 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -5,6 +5,7 @@ import { RouteStore } from "../../../server/RouteStore";
import * as Pdfjs from "pdfjs-dist";
import { Opt } from "../../../new_fields/Doc";
import "./PDFViewer.scss";
+import "pdfjs-dist/web/pdf_viewer.css";
interface IPDFViewerProps {
url: string;
@@ -52,8 +53,8 @@ class Viewer extends React.Component<IViewerProps> {
pdf={this.props.pdf}
page={i}
numPages={numPages}
- key={`${this.props.pdf ? this.props.pdf.fingerprint + `page${i + 1}` : "undefined"}`}
- name={`${this.props.pdf ? this.props.pdf.fingerprint + `page${i + 1}` : "undefined"}`}
+ key={`${this.props.pdf ? this.props.pdf.fingerprint + `-page${i + 1}` : "undefined"}`}
+ name={`${this.props.pdf ? this.props.pdf.fingerprint + `-page${i + 1}` : "undefined"}`}
{...this.props}
/>
))} }
@@ -149,24 +150,12 @@ class Page extends React.Component<IPageProps> {
}
}
- @action
- prevPage = (e: React.MouseEvent) => {
- if (this._currPage > 2 && this._state !== "rendering") {
- this._currPage = Math.max(this._currPage - 1, 1);
- this._page = undefined;
- this.loadPage(this.props.pdf!);
- this._state = "rendering";
- }
+ onPointerDown = (e: React.PointerEvent) => {
+ e.stopPropagation();
}
- @action
- nextPage = (e: React.MouseEvent) => {
- if (this._currPage < this.props.numPages - 1 && this._state !== "rendering") {
- this._currPage = Math.min(this._currPage + 1, this.props.numPages)
- this._page = undefined;
- this.loadPage(this.props.pdf!);
- this._state = "rendering";
- }
+ onPointerMove = (e: React.PointerEvent) => {
+ e.stopPropagation();
}
render() {
@@ -175,11 +164,7 @@ class Page extends React.Component<IPageProps> {
<div className="canvasContainer">
<canvas ref={this.canvas} />
</div>
- <div className="textlayer" ref={this.textLayer} style={{ "position": "relative", "top": `-${this._height}px`, "height": `${this._height}px` }} />
- {/* <div className="viewer-button-cont" style={{ "width": this._width / 10, "height": this._height / 20, "left": this._width * .9, "top": this._height * .95 }}>
- <div className="viewer-previousPage" onClick={this.prevPage}>&lt;</div>
- <div className="viewer-nextPage" onClick={this.nextPage}>&gt;</div>
- </div> */}
+ <div onPointerDown={this.onPointerDown} onPointerMove={this.onPointerMove} className="textlayer" ref={this.textLayer} style={{ "position": "relative", "top": `-${this._height}px`, "height": `${this._height}px` }} />
</div>
);
}