aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/PDFBox.tsx
diff options
context:
space:
mode:
authoreeng5 <eleanor.eng5@gmail.com>2019-11-19 17:47:13 -0500
committereeng5 <eleanor.eng5@gmail.com>2019-11-19 17:47:13 -0500
commit7d89d10a3d43755c267fd48e18701d457ae7aa1c (patch)
tree059312d4d2dfeaa96b5e272abc7608b0d68b96b4 /src/client/views/nodes/PDFBox.tsx
parentab285371f6fb2a4f1e64888bafbc84b602f23416 (diff)
parent667d196a2cbc8e237de5be9a6f7ec4ecca9d2bb5 (diff)
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into server_refactor
Diffstat (limited to 'src/client/views/nodes/PDFBox.tsx')
-rw-r--r--src/client/views/nodes/PDFBox.tsx134
1 files changed, 61 insertions, 73 deletions
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 63b412a23..5cfd4b019 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -1,10 +1,9 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, observable, runInAction, reaction, IReactionDisposer } from 'mobx';
+import { action, observable, runInAction, reaction, IReactionDisposer, trace, untracked, computed } from 'mobx';
import { observer } from "mobx-react";
import * as Pdfjs from "pdfjs-dist";
import "pdfjs-dist/web/pdf_viewer.css";
-import 'react-image-lightbox/style.css';
-import { Opt, WidthSym } from "../../../new_fields/Doc";
+import { Opt, WidthSym, Doc } from "../../../new_fields/Doc";
import { makeInterface } from "../../../new_fields/Schema";
import { ScriptField } from '../../../new_fields/ScriptField';
import { Cast } from "../../../new_fields/Types";
@@ -16,55 +15,57 @@ import { panZoomSchema } from '../collections/collectionFreeForm/CollectionFreeF
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { DocAnnotatableComponent } from "../DocComponent";
-import { InkingControl } from "../InkingControl";
import { PDFViewer } from "../pdf/PDFViewer";
-import { documentSchema } from "./DocumentView";
import { FieldView, FieldViewProps } from './FieldView';
import { pageSchema } from "./ImageBox";
import "./PDFBox.scss";
import React = require("react");
+import { documentSchema } from '../../../new_fields/documentSchemas';
type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>;
const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema);
@observer
export class PDFBox extends DocAnnotatableComponent<FieldViewProps, PdfDocument>(PdfDocument) {
- public static LayoutString(fieldExt?: string) { return FieldView.LayoutString(PDFBox, "data", fieldExt); }
+ public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PDFBox, fieldKey); }
private _keyValue: string = "";
private _valueValue: string = "";
private _scriptValue: string = "";
private _searchString: string = "";
+ private _initialScale: number = 0; // the initial scale of the PDF when first rendered which determines whether the document will be live on startup or not. Getting bigger after startup won't make it automatically be live.
private _everActive = false; // has this box ever had its contents activated -- if so, stop drawing the overlay title
private _pdfViewer: PDFViewer | undefined;
- private _searchRef: React.RefObject<HTMLInputElement> = React.createRef();
- private _keyRef: React.RefObject<HTMLInputElement> = React.createRef();
- private _valueRef: React.RefObject<HTMLInputElement> = React.createRef();
- private _scriptRef: React.RefObject<HTMLInputElement> = React.createRef();
- private _selectReaction: IReactionDisposer | undefined;
+ private _searchRef = React.createRef<HTMLInputElement>();
+ private _keyRef = React.createRef<HTMLInputElement>();
+ private _valueRef = React.createRef<HTMLInputElement>();
+ private _scriptRef = React.createRef<HTMLInputElement>();
+ private _selectReactionDisposer: IReactionDisposer | undefined;
@observable private _searching: boolean = false;
@observable private _flyout: boolean = false;
@observable private _pdf: Opt<Pdfjs.PDFDocumentProxy>;
@observable private _pageControls = false;
+ constructor(props: any) {
+ super(props);
+ this._initialScale = this.props.ScreenToLocalTransform().Scale;
+ }
+
componentWillUnmount() {
- this._selectReaction && this._selectReaction();
+ this._selectReactionDisposer && this._selectReactionDisposer();
}
componentDidMount() {
const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField);
if (pdfUrl instanceof PdfField) {
Pdfjs.getDocument(pdfUrl.url.pathname).promise.then(pdf => runInAction(() => this._pdf = pdf));
}
- this._selectReaction = reaction(() => this.props.isSelected(),
+ this._selectReactionDisposer = reaction(() => this.props.isSelected(),
() => {
- if (this.props.isSelected()) {
- document.removeEventListener("keydown", this.onKeyDown);
- document.addEventListener("keydown", this.onKeyDown);
- } else {
- document.removeEventListener("keydown", this.onKeyDown);
- }
+ document.removeEventListener("keydown", this.onKeyDown);
+ this.props.isSelected() && document.addEventListener("keydown", this.onKeyDown);
}, { fireImmediately: true });
}
+
loaded = (nw: number, nh: number, np: number) => {
this.dataDoc.numPages = np;
this.Document.nativeWidth = nw * 96 / 72;
@@ -76,8 +77,8 @@ export class PDFBox extends DocAnnotatableComponent<FieldViewProps, PdfDocument>
public prevAnnotation() { this._pdfViewer && this._pdfViewer.prevAnnotation(); }
public nextAnnotation() { this._pdfViewer && this._pdfViewer.nextAnnotation(); }
public backPage() { this._pdfViewer!.gotoPage((this.Document.curPage || 1) - 1); }
- public gotoPage = (p: number) => { this._pdfViewer!.gotoPage(p); };
public forwardPage() { this._pdfViewer!.gotoPage((this.Document.curPage || 1) + 1); }
+ public gotoPage = (p: number) => { this._pdfViewer!.gotoPage(p); };
@undoBatch
onKeyDown = action((e: KeyboardEvent) => {
@@ -87,12 +88,8 @@ export class PDFBox extends DocAnnotatableComponent<FieldViewProps, PdfDocument>
e.stopImmediatePropagation();
e.preventDefault();
}
- if (e.key === "PageDown" || e.key === "ArrowDown" || e.key === "ArrowRight") {
- this.forwardPage();
- }
- if (e.key === "PageUp" || e.key === "ArrowUp" || e.key === "ArrowLeft") {
- this.backPage();
- }
+ if (e.key === "PageDown" || e.key === "ArrowDown" || e.key === "ArrowRight") this.forwardPage();
+ if (e.key === "PageUp" || e.key === "ArrowUp" || e.key === "ArrowLeft") this.backPage();
});
@undoBatch
@@ -114,40 +111,33 @@ export class PDFBox extends DocAnnotatableComponent<FieldViewProps, PdfDocument>
private newValueChange = (e: React.ChangeEvent<HTMLInputElement>) => this._valueValue = e.currentTarget.value;
private newScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => this._scriptValue = e.currentTarget.value;
- whenActiveChanged = (isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive);
- active = () => this.props.isSelected() || this._isChildActive || this.props.renderDepth === 0;
+ whenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive));
setPdfViewer = (pdfViewer: PDFViewer) => { this._pdfViewer = pdfViewer; };
searchStringChanged = (e: React.ChangeEvent<HTMLInputElement>) => this._searchString = e.currentTarget.value;
settingsPanel() {
let pageBtns = <>
<button className="pdfBox-overlayButton-iconCont" key="back" title="Page Back"
- onPointerDown={(e) => e.stopPropagation()}
- onClick={() => this.backPage()}
- style={{ left: 50, top: 5, height: "30px", position: "absolute", pointerEvents: "all" }}>
+ onPointerDown={e => e.stopPropagation()} onClick={this.backPage} style={{ left: 50, top: 5 }}>
<FontAwesomeIcon style={{ color: "white" }} icon={"arrow-left"} size="sm" />
</button>
<button className="pdfBox-overlayButton-iconCont" key="fwd" title="Page Forward"
- onPointerDown={(e) => e.stopPropagation()}
- onClick={() => this.forwardPage()}
- style={{ left: 80, top: 5, height: "30px", position: "absolute", pointerEvents: "all" }}>
+ onPointerDown={e => e.stopPropagation()} onClick={this.forwardPage} style={{ left: 80, top: 5 }}>
<FontAwesomeIcon style={{ color: "white" }} icon={"arrow-right"} size="sm" />
</button>
</>;
- return !this.props.active() ? (null) :
+ return !this.active() ? (null) :
(<div className="pdfBox-ui" onKeyDown={e => e.keyCode === KeyCodes.BACKSPACE || e.keyCode === KeyCodes.DELETE ? e.stopPropagation() : true}
onPointerDown={e => e.stopPropagation()} style={{ display: this.active() ? "flex" : "none", position: "absolute", width: "100%", height: "100%", zIndex: 1, pointerEvents: "none" }}>
<div className="pdfBox-overlayCont" key="cont" onPointerDown={(e) => e.stopPropagation()} style={{ left: `${this._searching ? 0 : 100}%` }}>
<button className="pdfBox-overlayButton" title="Open Search Bar" />
- <input className="pdfBox-searchBar" placeholder="Search" autoFocus={true} ref={this._searchRef} onChange={this.searchStringChanged} onKeyDown={e => {
- e.keyCode === KeyCodes.ENTER && this.search(this._searchString, !e.shiftKey);
- }} />
+ <input className="pdfBox-searchBar" placeholder="Search" ref={this._searchRef} onChange={this.searchStringChanged} onKeyDown={e => e.keyCode === KeyCodes.ENTER && this.search(this._searchString, !e.shiftKey)} />
<button title="Search" onClick={e => this.search(this._searchString, !e.shiftKey)}>
<FontAwesomeIcon icon="search" size="sm" color="white" /></button>
- <button className="pdfBox-prevIcon " title="Previous Annotation" onClick={e => this.prevAnnotation()} >
+ <button className="pdfBox-prevIcon " title="Previous Annotation" onClick={this.prevAnnotation} >
<FontAwesomeIcon style={{ color: "white" }} icon={"arrow-up"} size="sm" />
</button>
- <button className="pdfBox-nextIcon" title="Next Annotation" onClick={e => this.nextAnnotation()} >
+ <button className="pdfBox-nextIcon" title="Next Annotation" onClick={this.nextAnnotation} >
<FontAwesomeIcon style={{ color: "white" }} icon={"arrow-down"} size="sm" />
</button>
</div>
@@ -202,40 +192,38 @@ export class PDFBox extends DocAnnotatableComponent<FieldViewProps, PdfDocument>
ContextMenu.Instance.addItem({ description: "Pdf Funcs...", subitems: funcs, icon: "asterisk" });
}
- _initialScale: number | undefined; // the initial scale of the PDF when first rendered which determines whether the document will be live on startup or not. Getting bigger after startup won't make it automatically be live....
- render() {
+
+ @computed get renderTitleBox() {
+ let classname = "pdfBox-cont" + (this.active() ? "-interactive" : "");
+ return <div className="pdfBox-title-outer" >
+ <div className={classname} >
+ <strong className="pdfBox-title" >{this.props.Document.title}</strong>
+ </div>
+ </div>;
+ }
+
+ isChildActive = () => this._isChildActive;
+ @computed get renderPdfView() {
const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField);
- let classname = "pdfBox-cont" + (InkingControl.Instance.selectedTool || !this.active ? "" : "-interactive");
- let noPdf = !(pdfUrl instanceof PdfField) || !this._pdf;
- if (this._initialScale === undefined) this._initialScale = this.props.ScreenToLocalTransform().Scale;
+ return <div className={"pdfBox-cont"} onContextMenu={this.specificContextMenu}>
+ <PDFViewer {...this.props} pdf={this._pdf!} url={pdfUrl!.url.pathname} active={this.props.active} loaded={this.loaded}
+ setPdfViewer={this.setPdfViewer} ContainingCollectionView={this.props.ContainingCollectionView}
+ renderDepth={this.props.renderDepth} PanelHeight={this.props.PanelHeight} PanelWidth={this.props.PanelWidth}
+ Document={this.props.Document} DataDoc={this.dataDoc} ContentScaling={this.props.ContentScaling}
+ addDocTab={this.props.addDocTab} focus={this.props.focus}
+ pinToPres={this.props.pinToPres} addDocument={this.addDocument}
+ ScreenToLocalTransform={this.props.ScreenToLocalTransform} select={this.props.select}
+ isSelected={this.props.isSelected} whenActiveChanged={this.whenActiveChanged}
+ isChildActive={this.isChildActive}
+ fieldKey={this.props.fieldKey} startupLive={this._initialScale < 2.5 ? true : false} />
+ {this.settingsPanel()}
+ </div>;
+ }
+
+ render() {
+ const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField, null);
if (this.props.isSelected() || this.props.Document.scrollY !== undefined) this._everActive = true;
- return (noPdf || (!this._everActive && this.props.ScreenToLocalTransform().Scale > 2.5) ?
- <div className="pdfBox-title-outer" >
- <div className={classname} >
- <strong className="pdfBox-title" >{` ${this.props.Document.title}`}</strong>
- </div>
- </div> :
- <div className={classname} style={{
- transformOrigin: "top left",
- width: this.props.Document.fitWidth ? `${100 / this.props.ContentScaling()}%` : undefined,
- height: this.props.Document.fitWidth ? `${100 / this.props.ContentScaling()}%` : undefined,
- transform: `scale(${this.props.Document.fitWidth ? this.props.ContentScaling() : 1})`
- }} onContextMenu={this.specificContextMenu} onPointerDown={(e: React.PointerEvent) => {
- let hit = document.elementFromPoint(e.clientX, e.clientY);
- if (hit && hit.localName === "span" && this.props.isSelected()) { // drag selecting text stops propagation
- e.button === 0 && e.stopPropagation();
- }
- }}>
- <PDFViewer {...this.props} pdf={this._pdf!} url={pdfUrl!.url.pathname} active={this.props.active} loaded={this.loaded}
- setPdfViewer={this.setPdfViewer} ContainingCollectionView={this.props.ContainingCollectionView}
- renderDepth={this.props.renderDepth} PanelHeight={this.props.PanelHeight} PanelWidth={this.props.PanelWidth}
- Document={this.props.Document} DataDoc={this.dataDoc} ContentScaling={this.props.ContentScaling}
- addDocTab={this.props.addDocTab} GoToPage={this.gotoPage} focus={this.props.focus}
- pinToPres={this.props.pinToPres} addDocument={this.props.addDocument}
- ScreenToLocalTransform={this.props.ScreenToLocalTransform} select={this.props.select}
- isSelected={this.props.isSelected} whenActiveChanged={this.whenActiveChanged}
- fieldKey={this.props.fieldKey} extensionDoc={this.extensionDoc} startupLive={this._initialScale < 2.5 ? true : false} />
- {this.settingsPanel()}
- </div>);
+ return !pdfUrl || !this._pdf || !this.extensionDoc || (!this._everActive && this.props.ScreenToLocalTransform().Scale > 2.5) ?
+ this.renderTitleBox : this.renderPdfView;
}
} \ No newline at end of file