aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBob Zeleznik <zzzman@gmail.com>2019-06-18 08:36:37 -0400
committerBob Zeleznik <zzzman@gmail.com>2019-06-18 08:36:37 -0400
commit2f5c38c6a0a5220c2a31931c34d94e199854d703 (patch)
treef801b748373eb9263828e601ee2b059e27f00fbd /src
parent62c781c0c79ac395c5e117d208a90485ff1ba599 (diff)
more streamlining
Diffstat (limited to 'src')
-rw-r--r--src/client/views/pdf/PDFViewer.tsx144
1 files changed, 57 insertions, 87 deletions
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 5149e48fd..645afc636 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -1,29 +1,23 @@
+import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
import { observer } from "mobx-react";
-import React = require("react");
-import { observable, action, runInAction, computed, IReactionDisposer, reaction, trace } from "mobx";
import * as Pdfjs from "pdfjs-dist";
-import { Opt, HeightSym, WidthSym, Doc, DocListCast } from "../../../new_fields/Doc";
-import "./PDFViewer.scss";
import "pdfjs-dist/web/pdf_viewer.css";
-import { PDFBox } from "../nodes/PDFBox";
-import Page from "./Page";
-import { NumCast, Cast, BoolCast, StrCast } from "../../../new_fields/Types";
+import * as rp from "request-promise";
+import { Dictionary } from "typescript-collections";
+import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../new_fields/Doc";
import { Id } from "../../../new_fields/FieldSymbols";
-import { DocUtils, Docs } from "../../documents/Documents";
-import { DocumentManager } from "../../util/DocumentManager";
-import { SelectionManager } from "../../util/SelectionManager";
import { List } from "../../../new_fields/List";
-import { DocumentContentsView } from "../nodes/DocumentContentsView";
-import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
-import { Transform } from "../../util/Transform";
-import { emptyFunction, returnTrue, returnFalse } from "../../../Utils";
-import { DocumentView } from "../nodes/DocumentView";
-import { DragManager } from "../../util/DragManager";
-import { Dictionary } from "typescript-collections";
-import * as rp from "request-promise";
-import { restProperty } from "babel-types";
+import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types";
+import { emptyFunction } from "../../../Utils";
import { DocServer } from "../../DocServer";
-import { number } from "prop-types";
+import { Docs, DocUtils } from "../../documents/Documents";
+import { DocumentManager } from "../../util/DocumentManager";
+import { DragManager } from "../../util/DragManager";
+import { DocumentView } from "../nodes/DocumentView";
+import { PDFBox } from "../nodes/PDFBox";
+import Page from "./Page";
+import "./PDFViewer.scss";
+import React = require("react");
export const scale = 2;
interface IPDFViewerProps {
@@ -49,14 +43,15 @@ export class PDFViewer extends React.Component<IPDFViewerProps> {
render() {
return (
<div ref={this._mainDiv}>
- <Viewer pdf={this._pdf} loaded={this.props.loaded} scrollY={this.props.scrollY} parent={this.props.parent} mainCont={this._mainDiv} url={this.props.url} />
+ {!this._pdf ? (null) :
+ <Viewer pdf={this._pdf} loaded={this.props.loaded} scrollY={this.props.scrollY} parent={this.props.parent} mainCont={this._mainDiv} url={this.props.url} />}
</div>
);
}
}
interface IViewerProps {
- pdf: Opt<Pdfjs.PDFDocumentProxy>;
+ pdf: Pdfjs.PDFDocumentProxy;
loaded: (nw: number, nh: number, np: number) => void;
scrollY: number;
parent: PDFBox;
@@ -77,37 +72,27 @@ class Viewer extends React.Component<IViewerProps> {
@observable private _isPage: string[] = [];
@observable private _pageSizes: { width: number, height: number }[] = [];
@observable private _annotations: Doc[] = [];
- @observable private _pointerEvents: "all" | "none" = "all";
@observable private _savedAnnotations: Dictionary<number, HTMLDivElement[]> = new Dictionary<number, HTMLDivElement[]>();
private _pageBuffer: number = 1;
- private _annotationLayer: React.RefObject<HTMLDivElement>;
+ private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
private _reactionDisposer?: IReactionDisposer;
private _annotationReactionDisposer?: IReactionDisposer;
private _dropDisposer?: DragManager.DragDropDisposer;
- constructor(props: IViewerProps) {
- super(props);
-
- this._annotationLayer = React.createRef();
- }
-
componentDidUpdate = (prevProps: IViewerProps) => {
- if (this.scrollY !== prevProps.scrollY && this._visibleElements.length) {
- this.renderPages(this.startIndex, this.endIndex, false);
+ if (this.scrollY !== prevProps.scrollY) {
+ this.renderPages();
}
}
@action
componentDidMount = () => {
- let wasSelected = this.props.parent.props.active();
this._reactionDisposer = reaction(
- () => [this.props.parent.props.active(), this.startIndex, this.props.pdf],
+ () => [this.props.parent.props.active(), this.startIndex, this.endIndex],
async () => {
await this.initialLoad();
- wasSelected = this.props.parent.props.active();
- runInAction(() => this._pointerEvents = wasSelected ? "none" : "all");
- this.renderPages(this.startIndex, this.endIndex, false);
+ this.renderPages();
}, { fireImmediately: true });
this._annotationReactionDisposer = reaction(
@@ -124,23 +109,15 @@ class Viewer extends React.Component<IViewerProps> {
@action
initialLoad = async () => {
- if (this.props.pdf && this._pageSizes.length === 0) {
+ if (this._pageSizes.length === 0) {
let pageSizes = Array<{ width: number, height: number }>(this.props.pdf.numPages);
for (let i = 0; i < this.props.pdf.numPages; i++) {
- await this.props.pdf.getPage(i + 1).then(page => runInAction(() => {
- pageSizes[i] = { width: page.view[2] * scale, height: page.view[3] * scale };
- if (i === 0) this.props.loaded(pageSizes[i].width, pageSizes[i].height, this.props.pdf!.numPages);
- }));
+ await this.props.pdf.getPage(i + 1).then(page => runInAction(() =>
+ pageSizes[i] = { width: page.view[2] * scale, height: page.view[3] * scale }));
}
- runInAction(() => {
- this._pageSizes = pageSizes;
- let divs = Array.from(Array(this._pageSizes.length).keys()).map(i => (
- <div key={`pdfviewer-placeholder-${i}`} className="pdfviewer-placeholder"
- style={{ width: this._pageSizes[i] ? this._pageSizes[i].width : 0, height: this._pageSizes[i] ? this._pageSizes[i].height : 0 }} />
- ));
- this._isPage = Array.from(Array(this._pageSizes.length).map(p => "none"));
- this._visibleElements = new Array<JSX.Element>(...divs);
- })
+ this.props.loaded(pageSizes[0].width, pageSizes[0].height, this.props.pdf.numPages);
+ runInAction(() =>
+ Array.from(Array((this._pageSizes = pageSizes).length).keys()).map(this.getPlaceholderPage))
}
}
@@ -199,14 +176,15 @@ class Viewer extends React.Component<IViewerProps> {
*/
@action
pageLoaded = (index: number, page: Pdfjs.PDFPageViewport): void => {
- this.props.pdf && this.props.loaded && this.props.loaded(page.width, page.height, this.props.pdf.numPages);
+ this.props.loaded(page.width, page.height, this.props.pdf.numPages);
}
@action
getPlaceholderPage = (page: number) => {
if (this._isPage[page] !== "none") {
this._isPage[page] = "none";
this._visibleElements[page] = (
- <div key={`pdfviewer-placeholder-${page}`} className="pdfviewer-placeholder" style={{ width: this._pageSizes[page] ? this._pageSizes[page].width : 0, height: this._pageSizes[page] ? this._pageSizes[page].height : 0 }} />
+ <div key={`placeholder-${page}`} className="pdfviewer-placeholder"
+ style={{ width: this._pageSizes[page].width, height: this._pageSizes[page].height }} />
);
}
}
@@ -219,8 +197,8 @@ class Viewer extends React.Component<IViewerProps> {
pdf={this.props.pdf}
page={page}
numPages={this.props.pdf!.numPages}
- key={`${this.props.pdf ? this.props.pdf.fingerprint + `-page${page + 1}` : "undefined"}`}
- name={`${this.props.pdf ? this.props.pdf.fingerprint + `-page${page + 1}` : "undefined"}`}
+ key={`rendered-${page + 1}`}
+ name={`${this.props.pdf.fingerprint + `-page${page + 1}`}`}
pageLoaded={this.pageLoaded}
parent={this.props.parent}
makePin={this.createPinAnnotation}
@@ -243,38 +221,33 @@ class Viewer extends React.Component<IViewerProps> {
this._isPage[page] = "image";
const address = this.props.url;
let res = JSON.parse(await rp.get(DocServer.prepend(`/thumbnail${address.substring("files/".length, address.length - ".pdf".length)}-${page + 1}.PNG`)));
- runInAction(() => this._visibleElements[page] = <img key={res.path} src={res.path} onError={handleError}
- style={{ width: `${parseInt(res.width) * scale}px`, height: `${parseInt(res.height) * scale}px` }} />);
+ runInAction(() => this._visibleElements[page] =
+ <img key={res.path} src={res.path} onError={handleError}
+ style={{ width: `${parseInt(res.width) * scale}px`, height: `${parseInt(res.height) * scale}px` }} />);
}
}
@computed get scrollY(): number { return this.props.scrollY; }
+ // startIndex: where to start rendering pages
@computed get startIndex(): number { return Math.max(0, this.getPageFromScroll(this.scrollY) - this._pageBuffer); }
+ // endIndex: where to end rendering pages
@computed get endIndex(): number {
- let width = this._pageSizes.map(i => i ? i.width : 0);
- return Math.min(this.props.pdf ? this.props.pdf.numPages - 1 : 0, this.getPageFromScroll(this.scrollY + Math.max(...width)) + this._pageBuffer);
+ let width = this._pageSizes.map(i => i.width);
+ return Math.min(this.props.pdf.numPages - 1, this.getPageFromScroll(this.scrollY + Math.max(...width)) + this._pageBuffer);
}
- /**
- * @param startIndex: where to start rendering pages
- * @param endIndex: where to end rendering pages
- * @param forceRender: (optional), force pdfs to re-render, even if the page already exists
- */
@action
- renderPages = (startIndex: number, endIndex: number, forceRender: boolean = false) => {
- if (this.props.pdf) {
- // unrender pages outside of the pdf by replacing them with empty stand-in divs
- for (let i = 0; i < this.props.pdf.numPages; i++) {
- if (i < startIndex || i > endIndex) {
- this.getPlaceholderPage(i);
+ renderPages = () => {
+ for (let i = 0; i < this.props.pdf.numPages; i++) {
+ if (i < this.startIndex || i > this.endIndex) {
+ this.getPlaceholderPage(i); // pages outside of the pdf use empty stand-in divs
+ } else {
+ if (this.props.parent.props.active()) {
+ this.getRenderedPage(i);
} else {
- if (this.props.parent.props.active()) {
- this.getRenderedPage(i);
- } else {
- this.getPageImage(i);
- }
+ this.getPageImage(i);
}
}
}
@@ -308,7 +281,6 @@ class Viewer extends React.Component<IViewerProps> {
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);
@@ -333,22 +305,16 @@ class Viewer extends React.Component<IViewerProps> {
getPageFromScroll = (vOffset: number) => {
let index = 0;
let currOffset = vOffset;
- while (index < this._pageSizes.length && currOffset - (this._pageSizes[index] ? this._pageSizes[index].height : 792 * scale) > 0) {
- currOffset -= this._pageSizes[index] ? this._pageSizes[index].height : this._pageSizes[0].height;
- index++;
+ while (index < this._pageSizes.length && currOffset - this._pageSizes[index].height > 0) {
+ currOffset -= this._pageSizes[index++].height;
}
return index;
}
-
getScrollFromPage = (index: number): number => {
let counter = 0;
- if (this.props.pdf && index < this.props.pdf.numPages) {
- for (let i = 0; i < index; i++) {
- if (this._pageSizes[i]) {
- counter += this._pageSizes[i].height;
- }
- }
+ for (let i = 0; i < Math.min(this.props.pdf.numPages, index); i++) {
+ counter += this._pageSizes[i].height;
}
return counter;
}
@@ -392,7 +358,11 @@ class Viewer extends React.Component<IViewerProps> {
<div className="viewer">
{this._visibleElements}
</div>
- <div className="pdfViewer-annotationLayer" style={{ height: this.props.parent.Document.nativeHeight, width: `100%`, pointerEvents: this._pointerEvents }}>
+ <div className="pdfViewer-annotationLayer"
+ style={{
+ height: this.props.parent.Document.nativeHeight, width: `100%`,
+ pointerEvents: this.props.parent.props.active() ? "none" : "all"
+ }}>
<div className="pdfViewer-annotationLayer-subCont" ref={this._annotationLayer}>
{this._annotations.map(anno => this.renderAnnotation(anno))}
</div>