diff options
Diffstat (limited to 'src/client/views/nodes/PDFBox.tsx')
-rw-r--r-- | src/client/views/nodes/PDFBox.tsx | 158 |
1 files changed, 98 insertions, 60 deletions
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 3baa6eb09..8370df6ba 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -1,13 +1,13 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, observable, runInAction, reaction, IReactionDisposer, trace } 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 { Opt, WidthSym, Doc } from "../../../new_fields/Doc"; +import { Opt, WidthSym, Doc, HeightSym } from "../../../new_fields/Doc"; import { makeInterface } from "../../../new_fields/Schema"; import { ScriptField } from '../../../new_fields/ScriptField'; -import { Cast } from "../../../new_fields/Types"; -import { PdfField } from "../../../new_fields/URLField"; +import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; +import { PdfField, URLField } from "../../../new_fields/URLField"; import { Utils } from '../../../Utils'; import { KeyCodes } from '../../northstar/utils/KeyCodes'; import { undoBatch } from '../../util/UndoManager'; @@ -21,6 +21,7 @@ import { pageSchema } from "./ImageBox"; import "./PDFBox.scss"; import React = require("react"); import { documentSchema } from '../../../new_fields/documentSchemas'; +import { url } from 'inspector'; type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>; const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema); @@ -32,7 +33,7 @@ export class PDFBox extends DocAnnotatableComponent<FieldViewProps, PdfDocument> private _valueValue: string = ""; private _scriptValue: string = ""; private _searchString: string = ""; - private _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. + 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.createRef<HTMLInputElement>(); @@ -46,25 +47,52 @@ export class PDFBox extends DocAnnotatableComponent<FieldViewProps, PdfDocument> @observable private _pdf: Opt<Pdfjs.PDFDocumentProxy>; @observable private _pageControls = false; + constructor(props: any) { + super(props); + this._initialScale = this.props.ScreenToLocalTransform().Scale; + const nw = this.Document.nativeWidth = NumCast(this.extensionDocSync.nativeWidth, NumCast(this.Document.nativeWidth, 927)); + const nh = this.Document.nativeHeight = NumCast(this.extensionDocSync.nativeHeight, NumCast(this.Document.nativeHeight, 1200)); + !this.Document.fitWidth && !this.Document.ignoreAspect && (this.Document.height = this.Document[WidthSym]() * (nh / nw)); + + const backup = "oldPath"; + const { Document } = this.props; + const { url: { href } } = Cast(Document[this.props.fieldKey], PdfField)!; + const pathCorrectionTest = /upload\_[a-z0-9]{32}.(.*)/g; + const matches = pathCorrectionTest.exec(href); + console.log("\nHere's the { url } being fed into the outer regex:"); + console.log(href); + console.log("And here's the 'properPath' build from the captured filename:\n"); + if (matches !== null && href.startsWith(window.location.origin)) { + const properPath = Utils.prepend(`/files/pdfs/${matches[0]}`); + console.log(properPath); + if (!properPath.includes(href)) { + console.log(`The two (url and proper path) were not equal`); + const proto = Doc.GetProto(Document); + proto[this.props.fieldKey] = new PdfField(properPath); + proto[backup] = href; + } else { + console.log(`The two (url and proper path) were equal`); + } + } else { + console.log("Outer matches was null!"); + } + } + componentWillUnmount() { 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._selectReactionDisposer = reaction(() => this.props.isSelected(), () => { document.removeEventListener("keydown", this.onKeyDown); - this.props.isSelected() && document.addEventListener("keydown", this.onKeyDown); + this.props.isSelected(true) && document.addEventListener("keydown", this.onKeyDown); }, { fireImmediately: true }); } loaded = (nw: number, nh: number, np: number) => { - this.dataDoc.numPages = np; - this.Document.nativeWidth = nw * 96 / 72; - this.Document.nativeHeight = nh * 96 / 72; + this.extensionDocSync.numPages = np; + this.extensionDocSync.nativeWidth = this.Document.nativeWidth = nw * 96 / 72; + this.extensionDocSync.nativeHeight = this.Document.nativeHeight = nh * 96 / 72; !this.Document.fitWidth && !this.Document.ignoreAspect && (this.Document.height = this.Document[WidthSym]() * (nh / nw)); } @@ -90,7 +118,7 @@ export class PDFBox extends DocAnnotatableComponent<FieldViewProps, PdfDocument> @undoBatch @action private applyFilter = () => { - let scriptText = this._scriptValue ? this._scriptValue : + const scriptText = this._scriptValue ? this._scriptValue : this._keyValue && this._valueValue ? `this.${this._keyValue} === ${this._valueValue}` : "true"; this.props.Document.filterScript = ScriptField.MakeFunction(scriptText); } @@ -106,53 +134,51 @@ 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); + 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 = <> + const 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={e => this.backPage()} style={{ left: 45, 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={e => this.forwardPage()} style={{ left: 45, top: 5 }}> <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-right"} size="sm" /> </button> </>; 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" }}> + onPointerDown={e => e.stopPropagation()} style={{ display: this.active() ? "flex" : "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" 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={this.prevAnnotation} > - <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-up"} size="sm" /> + <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-up"} size="lg" /> </button> <button className="pdfBox-nextIcon" title="Next Annotation" onClick={this.nextAnnotation} > - <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-down"} size="sm" /> + <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-down"} size="lg" /> </button> </div> - <button className="pdfBox-overlayButton" key="search" onClick={action(() => this._searching = !this._searching)} title="Open Search Bar" style={{ bottom: 8, right: 0 }}> + <button className="pdfBox-overlayButton" key="search" onClick={action(() => this._searching = !this._searching)} title="Open Search Bar" style={{ bottom: 0, right: 0 }}> <div className="pdfBox-overlayButton-arrow" onPointerDown={(e) => e.stopPropagation()}></div> <div className="pdfBox-overlayButton-iconCont" onPointerDown={(e) => e.stopPropagation()}> - <FontAwesomeIcon style={{ color: "white", padding: 5 }} icon={this._searching ? "times" : "search"} size="3x" /></div> + <FontAwesomeIcon style={{ color: "white" }} icon={this._searching ? "times" : "search"} size="lg" /></div> </button> <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" }} + style={{ left: 5, top: 5, height: "20px", width: "20px", position: "absolute", pointerEvents: "all" }} onClick={action(() => this._pageControls = !this._pageControls)} /> {this._pageControls ? pageBtns : (null)} <div className="pdfBox-settingsCont" key="settings" onPointerDown={(e) => e.stopPropagation()}> <button className="pdfBox-settingsButton" onClick={action(() => this._flyout = !this._flyout)} title="Open Annotation Settings" > <div className="pdfBox-settingsButton-arrow" style={{ transform: `scaleX(${this._flyout ? -1 : 1})` }} /> <div className="pdfBox-settingsButton-iconCont"> - <FontAwesomeIcon style={{ color: "white", padding: 5 }} icon="cog" size="3x" /> + <FontAwesomeIcon style={{ color: "white" }} icon="cog" size="lg" /> </div> </button> <div className="pdfBox-settingsFlyout" style={{ right: `${this._flyout ? 20 : -600}px` }} > @@ -183,46 +209,58 @@ export class PDFBox extends DocAnnotatableComponent<FieldViewProps, PdfDocument> specificContextMenu = (e: React.MouseEvent): void => { const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField); - let funcs: ContextMenuProps[] = []; + const funcs: ContextMenuProps[] = []; pdfUrl && funcs.push({ description: "Copy path", event: () => Utils.CopyText(pdfUrl.url.pathname), icon: "expand-arrows-alt" }); funcs.push({ description: "Toggle Fit Width " + (this.Document.fitWidth ? "Off" : "On"), event: () => this.Document.fitWidth = !this.Document.fitWidth, icon: "expand-arrows-alt" }); ContextMenu.Instance.addItem({ description: "Pdf Funcs...", subitems: funcs, icon: "asterisk" }); } - render() { - trace(); + @computed get contentScaling() { return this.props.ContentScaling(); } + @computed get renderTitleBox() { + const classname = "pdfBox" + (this.active() ? "-interactive" : ""); + return <div className={classname} style={{ + width: !this.props.Document.fitWidth ? this.Document.nativeWidth || 0 : `${100 / this.contentScaling}%`, + height: !this.props.Document.fitWidth ? this.Document.nativeHeight || 0 : `${100 / this.contentScaling}%`, + transform: `scale(${this.contentScaling})` + }} > + <div className="pdfBox-title-outer"> + <strong className="pdfBox-title" >{this.props.Document.title}</strong> + </div> + </div>; + } + + isChildActive = (outsideReaction?: boolean) => this._isChildActive; + @computed get renderPdfView() { const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField); - let classname = "pdfBox-cont" + (this.active() ? "-interactive" : ""); - let noPdf = !(pdfUrl instanceof PdfField) || !this._pdf; - if (this._initialScale === undefined) this._initialScale = this.props.ScreenToLocalTransform().Scale; + return <div className={"pdfBox"} 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} + addDocTab={this.props.addDocTab} focus={this.props.focus} + pinToPres={this.props.pinToPres} addDocument={this.addDocument} + Document={this.props.Document} DataDoc={this.dataDoc} ContentScaling={this.props.ContentScaling} + 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>; + } + + _pdfjsRequested = false; + render() { + const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField, null); if (this.props.isSelected() || this.props.Document.scrollY !== undefined) this._everActive = true; - return (!this.extensionDoc || 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={{ - 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 => { - 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} 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} - fieldKey={this.props.fieldKey} startupLive={this._initialScale < 2.5 ? true : false} /> - {this.settingsPanel()} - </div>); + if (pdfUrl && this.extensionDoc && (this._everActive || (this.extensionDoc.nativeWidth && this.props.ScreenToLocalTransform().Scale < 2.5))) { + if (pdfUrl instanceof PdfField && this._pdf) { + return this.renderPdfView; + } + if (!this._pdfjsRequested) { + this._pdfjsRequested = true; + Pdfjs.getDocument(pdfUrl.url.href).promise.then(pdf => runInAction(() => this._pdf = pdf)); + } + } + return this.renderTitleBox; } }
\ No newline at end of file |