aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package-lock.json33
-rw-r--r--package.json3
-rw-r--r--src/client/util/DragManager.ts18
-rw-r--r--src/client/views/nodes/PDFNode.tsx40
-rw-r--r--src/fields/KeyStore.ts1
5 files changed, 67 insertions, 28 deletions
diff --git a/package-lock.json b/package-lock.json
index 4c26734f6..b8f18acbc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3412,14 +3412,12 @@
"balanced-match": {
"version": "1.0.0",
"resolved": false,
- "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
- "optional": true
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"brace-expansion": {
"version": "1.1.11",
"resolved": false,
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -3434,20 +3432,17 @@
"code-point-at": {
"version": "1.1.0",
"resolved": false,
- "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
- "optional": true
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
},
"concat-map": {
"version": "0.0.1",
"resolved": false,
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
- "optional": true
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"console-control-strings": {
"version": "1.1.0",
"resolved": false,
- "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
- "optional": true
+ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
},
"core-util-is": {
"version": "1.0.2",
@@ -3564,8 +3559,7 @@
"inherits": {
"version": "2.0.3",
"resolved": false,
- "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
- "optional": true
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"ini": {
"version": "1.3.5",
@@ -3577,7 +3571,6 @@
"version": "1.0.0",
"resolved": false,
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
- "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -3592,7 +3585,6 @@
"version": "3.0.4",
"resolved": false,
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
- "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -3600,14 +3592,12 @@
"minimist": {
"version": "0.0.8",
"resolved": false,
- "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
- "optional": true
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
},
"minipass": {
"version": "2.3.5",
"resolved": false,
"integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
- "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -3626,7 +3616,6 @@
"version": "0.5.1",
"resolved": false,
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
- "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -3707,8 +3696,7 @@
"number-is-nan": {
"version": "1.0.1",
"resolved": false,
- "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
- "optional": true
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
},
"object-assign": {
"version": "4.1.1",
@@ -3720,7 +3708,6 @@
"version": "1.4.0",
"resolved": false,
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
- "optional": true,
"requires": {
"wrappy": "1"
}
@@ -3842,7 +3829,6 @@
"version": "1.0.2",
"resolved": false,
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
- "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -4332,6 +4318,11 @@
"integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
"dev": true
},
+ "html-to-image": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-0.1.0.tgz",
+ "integrity": "sha512-/VLH+jjGQgLDs+BlVDVAzI1rdghYfFWFcPmFHChiD3UHMmckyDuvJpH3N3lli0elJkWfyv/EKrWNXTxm3mg4oQ=="
+ },
"http-deceiver": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
diff --git a/package.json b/package.json
index 7112d3672..271acfd0b 100644
--- a/package.json
+++ b/package.json
@@ -67,8 +67,8 @@
"@types/socket.io-client": "^1.4.32",
"@types/typescript": "^2.0.0",
"@types/uuid": "^3.4.4",
- "babel-runtime": "^6.26.0",
"@types/webpack": "^4.4.24",
+ "babel-runtime": "^6.26.0",
"bcrypt-nodejs": "0.0.3",
"bluebird": "^3.5.3",
"body-parser": "^1.18.3",
@@ -80,6 +80,7 @@
"expressjs": "^1.0.1",
"flexlayout-react": "^0.3.3",
"golden-layout": "^1.5.9",
+ "html-to-image": "^0.1.0",
"i": "^0.3.6",
"jsonwebtoken": "^8.4.0",
"jsx-to-string": "^1.4.0",
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 60910a40b..63f5616a9 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -3,6 +3,8 @@ import { CollectionDockingView } from "../views/collections/CollectionDockingVie
import { Document } from "../../fields/Document"
import { action } from "mobx";
import { DocumentView } from "../views/nodes/DocumentView";
+import { ImageField } from "../../fields/ImageField";
+import { KeyStore } from "../../fields/KeyStore";
export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Document) {
let onRowMove = action((e: PointerEvent): void => {
@@ -105,7 +107,19 @@ export namespace DragManager {
const scaleX = rect.width / w, scaleY = rect.height / h;
let x = rect.left, y = rect.top;
// const offsetX = e.x - rect.left, offsetY = e.y - rect.top;
- let dragElement = ele.cloneNode(true) as HTMLElement;
+
+ // bcz: PDFs don't show up if you clone them -- presumably because they contain a canvas.
+ // however, PDF's have a thumbnail field that contains an image of the current page.
+ // so we use this image instead of the cloned element if it's present.
+ const docView: DocumentView = dragData["documentView"];
+ const doc: Document = docView ? docView.props.Document : dragData["document"];
+ let thumbnail = doc.GetT(KeyStore.Thumbnail, ImageField);
+ let img = thumbnail ? new Image() : null;
+ if (thumbnail) {
+ img!.src = thumbnail.toString();
+ }
+ let dragElement = img ? img : ele.cloneNode(true) as HTMLElement;
+
dragElement.style.opacity = "0.7";
dragElement.style.position = "absolute";
dragElement.style.bottom = "";
@@ -140,8 +154,6 @@ export namespace DragManager {
y += e.movementY;
if (e.shiftKey) {
abortDrag();
- const docView: DocumentView = dragData["documentView"];
- const doc: Document = docView ? docView.props.Document : dragData["document"];
CollectionDockingView.Instance.StartOtherDrag(doc, { pageX: e.pageX, pageY: e.pageY, preventDefault: () => { }, button: 0 });
}
dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`;
diff --git a/src/client/views/nodes/PDFNode.tsx b/src/client/views/nodes/PDFNode.tsx
index b80283065..0390d5e0d 100644
--- a/src/client/views/nodes/PDFNode.tsx
+++ b/src/client/views/nodes/PDFNode.tsx
@@ -1,4 +1,4 @@
-import { action, observable } from 'mobx';
+import { action, observable, _interceptReads } from 'mobx';
import { observer } from "mobx-react";
import Measure from "react-measure";
import 'react-image-lightbox/style.css';
@@ -15,6 +15,9 @@ import { KeyStore } from '../../../fields/KeyStore';
import "./PDFNode.scss";
import { PDFField } from '../../../fields/PDFField';
import { FieldWaiting } from '../../../fields/Field';
+import { ImageField } from '../../../fields/ImageField';
+import * as htmlToImage from "html-to-image";
+import { url } from 'inspector';
/** ALSO LOOK AT: Annotation.tsx, Sticky.tsx
* This method renders PDF and puts all kinds of functionalities such as annotation, highlighting,
@@ -94,6 +97,7 @@ export class PDFNode extends React.Component<FieldViewProps> {
if (this.perPage[this.page - 1]) {
this.pageInfo = this.perPage[this.page - 1];
}
+ this.saveThumbnail();
}
}
@@ -110,6 +114,7 @@ export class PDFNode extends React.Component<FieldViewProps> {
if (this.perPage[this.page - 1]) {
this.pageInfo = this.perPage[this.page - 1];
}
+ this.saveThumbnail();
}
}
@@ -288,7 +293,6 @@ export class PDFNode extends React.Component<FieldViewProps> {
*/
@action
onPointerUp = (e: React.PointerEvent) => {
-
if (this._highlightToolOn) {
this.highlight("rgba(76, 175, 80, 0.3)"); //highlights to this default color.
this._highlightToolOn = false;
@@ -314,7 +318,7 @@ export class PDFNode extends React.Component<FieldViewProps> {
}
this._toolOn = false;
}
-
+ this._interactive = true;
}
/**
@@ -392,8 +396,23 @@ export class PDFNode extends React.Component<FieldViewProps> {
}
+ @observable _interactive: boolean = false;
@action
+ saveThumbnail = () => {
+ setTimeout(() => {
+ var me = this;
+ htmlToImage.toPng(this._mainDiv.current!,
+ { width: me.props.doc.GetNumber(KeyStore.NativeWidth, 0), height: me.props.doc.GetNumber(KeyStore.NativeHeight, 0), quality: 0.5 })
+ .then(function (dataUrl: string) {
+ me.props.doc.SetData(KeyStore.Thumbnail, new URL(dataUrl), ImageField);
+ })
+ .catch(function (error: any) {
+ console.error('oops, something went wrong!', error);
+ });
+ }, 1000);
+ }
+ @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 PDF
@@ -402,8 +421,23 @@ export class PDFNode extends React.Component<FieldViewProps> {
if (!this.props.doc.GetNumber(KeyStore.NativeHeight, 0)) {
this.props.doc.SetNumber(KeyStore.NativeHeight, nativeWidth * r.entry.height / r.entry.width);
}
+ if (!this.props.doc.GetT(KeyStore.Thumbnail, ImageField)) {
+ this.saveThumbnail();
+ }
}
render() {
+ let field = this.props.doc.Get(KeyStore.Thumbnail);
+ if (!this._interactive && field) {
+ let path = field == FieldWaiting ? "https://image.flaticon.com/icons/svg/66/66163.svg" :
+ field instanceof ImageField ? field.Data.href : "http://cs.brown.edu/people/bcz/prairie.jpg";
+ return (
+ <div className="pdfNode-cont" ref={this._mainDiv}
+ onPointerDown={this.onPointerDown}
+ onPointerUp={this.onPointerUp}
+ >
+ <img src={path} width="100%" />
+ </div>);
+ }
const renderHeight = 2400;
let xf = this.props.doc.GetNumber(KeyStore.NativeHeight, 0) / renderHeight;
var pdfUrl = this.props.doc.GetT(this.props.fieldKey, PDFField);
diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts
index a3b39735d..1327bd9f4 100644
--- a/src/fields/KeyStore.ts
+++ b/src/fields/KeyStore.ts
@@ -26,4 +26,5 @@ export namespace KeyStore {
export const Caption = new Key("Caption");
export const ActiveFrame = new Key("ActiveFrame");
export const DocumentText = new Key("DocumentText");
+ export const Thumbnail = new Key("Thumbnail");
}