aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/PDFBox.tsx
diff options
context:
space:
mode:
authorStanley Yip <stanley_yip@brown.edu>2019-10-13 15:58:23 -0400
committerStanley Yip <stanley_yip@brown.edu>2019-10-13 15:58:23 -0400
commitb50381f4872d4e5eaa6d1d8949ea4e10d468cfd8 (patch)
treec2939d230a5618aa609e4db84bfdee923bad80bd /src/client/views/nodes/PDFBox.tsx
parentbd796f24677b2aacd32a371da6d2b7c7eb354018 (diff)
parentbaf6ed901d341cade58741d363bbc475519558ae (diff)
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into interaction_stanley
Diffstat (limited to 'src/client/views/nodes/PDFBox.tsx')
-rw-r--r--src/client/views/nodes/PDFBox.tsx66
1 files changed, 47 insertions, 19 deletions
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 88cd2cdc4..63b412a23 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -1,17 +1,21 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, IReactionDisposer, observable, reaction, runInAction, untracked, trace } from 'mobx';
+import { action, observable, runInAction, reaction, IReactionDisposer } 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 { Doc, Opt, WidthSym } from "../../../new_fields/Doc";
+import { Opt, WidthSym } from "../../../new_fields/Doc";
import { makeInterface } from "../../../new_fields/Schema";
import { ScriptField } from '../../../new_fields/ScriptField';
-import { Cast, NumCast } from "../../../new_fields/Types";
+import { Cast } from "../../../new_fields/Types";
import { PdfField } from "../../../new_fields/URLField";
+import { Utils } from '../../../Utils';
import { KeyCodes } from '../../northstar/utils/KeyCodes';
+import { undoBatch } from '../../util/UndoManager';
import { panZoomSchema } from '../collections/collectionFreeForm/CollectionFreeFormView';
-import { DocComponent } from "../DocComponent";
+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";
@@ -19,41 +23,47 @@ import { FieldView, FieldViewProps } from './FieldView';
import { pageSchema } from "./ImageBox";
import "./PDFBox.scss";
import React = require("react");
-import { undoBatch } from '../../util/UndoManager';
-import { ContextMenuProps } from '../ContextMenuItem';
-import { ContextMenu } from '../ContextMenu';
-import { Utils } from '../../../Utils';
type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>;
const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema);
@observer
-export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocument) {
+export class PDFBox extends DocAnnotatableComponent<FieldViewProps, PdfDocument>(PdfDocument) {
public static LayoutString(fieldExt?: string) { return FieldView.LayoutString(PDFBox, "data", fieldExt); }
private _keyValue: string = "";
private _valueValue: string = "";
private _scriptValue: string = "";
private _searchString: string = "";
- private _isChildActive = false;
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;
@observable private _searching: boolean = false;
@observable private _flyout: boolean = false;
@observable private _pdf: Opt<Pdfjs.PDFDocumentProxy>;
@observable private _pageControls = false;
- @computed get extensionDoc() { return Doc.fieldExtensionDoc(this.dataDoc, this.props.fieldKey); }
- @computed get dataDoc() { return this.props.DataDoc && this.props.Document.isTemplate ? this.props.DataDoc : Doc.GetProto(this.props.Document); }
-
+ componentWillUnmount() {
+ this._selectReaction && this._selectReaction();
+ }
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(),
+ () => {
+ if (this.props.isSelected()) {
+ document.removeEventListener("keydown", this.onKeyDown);
+ document.addEventListener("keydown", this.onKeyDown);
+ } else {
+ document.removeEventListener("keydown", this.onKeyDown);
+ }
+ }, { fireImmediately: true });
}
loaded = (nw: number, nh: number, np: number) => {
this.dataDoc.numPages = np;
@@ -65,9 +75,25 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
public search(string: string, fwd: boolean) { this._pdfViewer && this._pdfViewer.search(string, fwd); }
public prevAnnotation() { this._pdfViewer && this._pdfViewer.prevAnnotation(); }
public nextAnnotation() { this._pdfViewer && this._pdfViewer.nextAnnotation(); }
- public backPage() { this._pdfViewer!.gotoPage(NumCast(this.props.Document.curPage) - 1); }
+ public backPage() { this._pdfViewer!.gotoPage((this.Document.curPage || 1) - 1); }
public gotoPage = (p: number) => { this._pdfViewer!.gotoPage(p); };
- public forwardPage() { this._pdfViewer!.gotoPage(NumCast(this.props.Document.curPage) + 1); }
+ public forwardPage() { this._pdfViewer!.gotoPage((this.Document.curPage || 1) + 1); }
+
+ @undoBatch
+ onKeyDown = action((e: KeyboardEvent) => {
+ if (e.key === "f" && e.ctrlKey) {
+ this._searching = true;
+ setTimeout(() => this._searchRef.current && this._searchRef.current.focus(), 100);
+ 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();
+ }
+ });
@undoBatch
@action
@@ -113,7 +139,9 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
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" onChange={this.searchStringChanged} onKeyDown={e => e.keyCode === KeyCodes.ENTER && this.search(this._searchString, !e.shiftKey)} />
+ <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);
+ }} />
<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()} >
@@ -128,7 +156,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
<div className="pdfBox-overlayButton-iconCont" onPointerDown={(e) => e.stopPropagation()}>
<FontAwesomeIcon style={{ color: "white", padding: 5 }} icon={this._searching ? "times" : "search"} size="3x" /></div>
</button>
- <input value={`${NumCast(this.props.Document.curPage)}`}
+ <input value={`${(this.Document.curPage || 1)}`}
onChange={e => this.gotoPage(Number(e.currentTarget.value))}
style={{ left: 20, top: 5, height: "30px", width: "30px", position: "absolute", pointerEvents: "all" }}
onClick={action(() => this._pageControls = !this._pageControls)} />
@@ -174,7 +202,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
ContextMenu.Instance.addItem({ description: "Pdf Funcs...", subitems: funcs, icon: "asterisk" });
}
- _initialScale: number | undefined;
+ _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() {
const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField);
let classname = "pdfBox-cont" + (InkingControl.Instance.selectedTool || !this.active ? "" : "-interactive");
@@ -206,7 +234,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
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} fieldExtensionDoc={this.extensionDoc} startupLive={this._initialScale < 2.5 ? true : false} />
+ fieldKey={this.props.fieldKey} extensionDoc={this.extensionDoc} startupLive={this._initialScale < 2.5 ? true : false} />
{this.settingsPanel()}
</div>);
}