import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, IReactionDisposer, observable, reaction, runInAction } 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, WidthSym, Opt } from "../../../new_fields/Doc"; import { makeInterface } from "../../../new_fields/Schema"; import { ScriptField } from '../../../new_fields/ScriptField'; import { BoolCast, Cast, NumCast } from "../../../new_fields/Types"; import { PdfField } from "../../../new_fields/URLField"; import { KeyCodes } from '../../northstar/utils/KeyCodes'; import { CompileScript } from '../../util/Scripting'; import { DocComponent } from "../DocComponent"; import { InkingControl } from "../InkingControl"; import { PDFViewer } from "../pdf/PDFViewer"; import { positionSchema } from "./DocumentView"; import { FieldView, FieldViewProps } from './FieldView'; import { pageSchema } from "./ImageBox"; import "./PDFBox.scss"; import React = require("react"); type PdfDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>; const PdfDocument = makeInterface(positionSchema, pageSchema); export const handleBackspace = (e: React.KeyboardEvent) => { if (e.keyCode === KeyCodes.BACKSPACE) e.stopPropagation(); }; @observer export class PDFBox extends DocComponent(PdfDocument) { public static LayoutString() { return FieldView.LayoutString(PDFBox); } @observable private _flyout: boolean = false; @observable private _alt = false; @observable private _pdf: Opt; @computed get containingCollectionDocument() { return this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document; } @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document; } @computed get fieldExtensionDoc() { return Doc.resolvedFieldDataDoc(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, "true"); } private _mainCont: React.RefObject = React.createRef(); private _reactionDisposer?: IReactionDisposer; private _keyValue: string = ""; private _valueValue: string = ""; private _scriptValue: string = ""; private _keyRef: React.RefObject = React.createRef(); private _valueRef: React.RefObject = React.createRef(); private _scriptRef: React.RefObject = React.createRef(); componentDidMount() { this.props.setPdfBox && this.props.setPdfBox(this); const pdfUrl = Cast(this.props.Document.data, PdfField); if (pdfUrl instanceof PdfField) { Pdfjs.getDocument(pdfUrl.url.pathname).promise.then(pdf => runInAction(() => this._pdf = pdf)); } this._reactionDisposer = reaction( () => this.props.Document.panY, () => this._mainCont.current && this._mainCont.current.scrollTo({ top: NumCast(this.Document.panY), behavior: "auto" }) ); } componentWillUnmount() { this._reactionDisposer && this._reactionDisposer(); } public GetPage() { return Math.floor(NumCast(this.props.Document.panY) / NumCast(this.dataDoc.nativeHeight)) + 1; } @action public BackPage() { let cp = Math.ceil(NumCast(this.props.Document.panY) / NumCast(this.dataDoc.nativeHeight)) + 1; cp = cp - 1; if (cp > 0) { this.props.Document.curPage = cp; this.props.Document.panY = (cp - 1) * NumCast(this.dataDoc.nativeHeight); } } @action public GotoPage(p: number) { if (p > 0 && p <= NumCast(this.props.Document.numPages)) { this.props.Document.curPage = p; this.props.Document.panY = (p - 1) * NumCast(this.dataDoc.nativeHeight); } } @action public ForwardPage() { let cp = this.GetPage() + 1; if (cp <= NumCast(this.props.Document.numPages)) { this.props.Document.curPage = cp; this.props.Document.panY = (cp - 1) * NumCast(this.dataDoc.nativeHeight); } } @action setPanY = (y: number) => { this.containingCollectionDocument && (this.containingCollectionDocument.panY = y); } @action private applyFilter = () => { let scriptText = this._scriptValue.length > 0 ? this._scriptValue : this._keyValue.length > 0 && this._valueValue.length > 0 ? `return this.${this._keyValue} === ${this._valueValue}` : "return true"; let script = CompileScript(scriptText, { params: { this: Doc.name } }); script.compiled && (this.props.Document.filterScript = new ScriptField(script)); } scrollTo = (y: number) => { this._mainCont.current && this._mainCont.current.scrollTo({ top: Math.max(y - (this._mainCont.current.offsetHeight / 2), 0), behavior: "auto" }); } private resetFilters = () => { this._keyValue = this._valueValue = ""; this._scriptValue = "return true"; this._keyRef.current && (this._keyRef.current.value = ""); this._valueRef.current && (this._valueRef.current.value = ""); this._scriptRef.current && (this._scriptRef.current.value = ""); this.applyFilter(); } private newKeyChange = (e: React.ChangeEvent) => this._keyValue = e.currentTarget.value; private newValueChange = (e: React.ChangeEvent) => this._valueValue = e.currentTarget.value; private newScriptChange = (e: React.ChangeEvent) => this._scriptValue = e.currentTarget.value; settingsPanel() { return !this.props.active() ? (null) : (
e.stopPropagation()}>
Annotation View Settings
); } loaded = (nw: number, nh: number, np: number) => { this.dataDoc.numPages = np; if (!this.dataDoc.nativeWidth || !this.dataDoc.nativeHeight || !this.dataDoc.scrollHeight) { let oldaspect = NumCast(this.dataDoc.nativeHeight) / NumCast(this.dataDoc.nativeWidth, 1); this.dataDoc.nativeWidth = nw; this.dataDoc.nativeHeight = this.dataDoc.nativeHeight ? nw * oldaspect : nh; this.dataDoc.height = this.dataDoc[WidthSym]() * (nh / nw); this.dataDoc.scrollHeight = np * this.dataDoc.nativeHeight; } } @action onScroll = (e: React.UIEvent) => { if (e.currentTarget && this.containingCollectionDocument) { this.containingCollectionDocument.panTransformType = "None"; this.containingCollectionDocument.panY = e.currentTarget.scrollTop; } } render() { const pdfUrl = Cast(this.props.Document.data, PdfField); let classname = "pdfBox-cont" + (this.props.active() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : ""); return (!(pdfUrl instanceof PdfField) || !this._pdf ?
{`pdf, ${this.props.Document.data}, not found`}
:
{this.settingsPanel()}
); } }