diff options
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 1 | ||||
-rw-r--r-- | src/client/views/nodes/FieldView.tsx | 1 | ||||
-rw-r--r-- | src/client/views/nodes/PDFBox.scss | 41 | ||||
-rw-r--r-- | src/client/views/nodes/PDFBox.tsx | 124 | ||||
-rw-r--r-- | src/client/views/pdf/PDFViewer.tsx | 6 |
5 files changed, 59 insertions, 114 deletions
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 759c064b4..d1d150027 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -261,6 +261,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu document.addEventListener("pointerup", this.onPointerUp); } onPointerMove = (e: PointerEvent): void => { + console.log("Move " + e.clientX + " " + this.props.Document.title); if (e.cancelBubble && this.active) { document.removeEventListener("pointermove", this.onPointerMove); } diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 49fc2263d..ec1b03a40 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -50,7 +50,6 @@ export interface FieldViewProps { PanelWidth: () => number; PanelHeight: () => number; setVideoBox?: (player: VideoBox) => void; - setPdfBox?: (player: PDFBox) => void; ContentScaling: () => number; ChromeHeight?: () => number; } diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index 2147292d6..d82bcf02f 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -10,15 +10,16 @@ .pdfBox-cont { pointer-events: none; - .pdfPage-textlayer { - span { - pointer-events: none !important; - user-select: none; - } - } .collectionFreeFormView-none { pointer-events: none; } + .pdfViewer-text { + .textLayer { + span { + user-select: none; + } + } + } } .pdfBox-cont-interactive { @@ -32,21 +33,6 @@ } } -.react-pdf__Page { - transform-origin: left top; - position: absolute; - top: 0; - left: 0; -} - -.react-pdf__Page__textContent span { - user-select: text; -} - -.react-pdf__Document { - position: absolute; -} - .pdfBox-settingsCont { position: absolute; @@ -124,7 +110,7 @@ overflow: hidden; transition: left .5s; - .pdfBox-overlaySearchBar { + .pdfBox-searchBar { width: 70%; font-size: 14px; } @@ -149,7 +135,9 @@ transition: all 0.5s; } - .pdfBox-overlayButton-iconCont { + .pdfBox-overlayButton-iconCont, + .pdfBox-nextIcon, + .pdfBox-prevIcon { background: #121721; height: 30px; width: 70px; @@ -165,4 +153,9 @@ background: none; } - +.pdfBox-nextIcon { + left: 20; top: 5; height: 30px; position: absolute; +} +.pdfBox-prevIcon { + left: 50; top: 5; height: 30px; position: absolute; +} diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 30f4ce392..6aa8aded9 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -6,7 +6,7 @@ import "pdfjs-dist/web/pdf_viewer.css"; import 'react-image-lightbox/style.css'; import { Doc, Opt, WidthSym } from "../../../new_fields/Doc"; import { makeInterface } from "../../../new_fields/Schema"; -import { ComputedField, ScriptField } from '../../../new_fields/ScriptField'; +import { ScriptField } from '../../../new_fields/ScriptField'; import { Cast, NumCast } from "../../../new_fields/Types"; import { PdfField } from "../../../new_fields/URLField"; import { KeyCodes } from '../../northstar/utils/KeyCodes'; @@ -19,7 +19,7 @@ import { FieldView, FieldViewProps } from './FieldView'; import { pageSchema } from "./ImageBox"; import "./PDFBox.scss"; import React = require("react"); -import { CollectionSchemaBooleanCell } from '../collections/CollectionSchemaCells'; +import { undoBatch } from '../../util/UndoManager'; type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>; const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema); @@ -27,73 +27,48 @@ const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema); @observer export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocument) { public static LayoutString(fieldExt?: string) { return FieldView.LayoutString(PDFBox, "data", fieldExt); } - private _reactionDisposer?: IReactionDisposer; private _keyValue: string = ""; private _valueValue: string = ""; private _scriptValue: string = ""; private _searchString: string = ""; - @observable private _searching: boolean = false; + private _isChildActive = false; private _pdfViewer: PDFViewer | undefined; private _keyRef: React.RefObject<HTMLInputElement> = React.createRef(); private _valueRef: React.RefObject<HTMLInputElement> = React.createRef(); private _scriptRef: React.RefObject<HTMLInputElement> = React.createRef(); + @observable private _searching: boolean = false; @observable private _flyout: boolean = false; - @observable private _alt = 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); } componentDidMount() { - this.props.setPdfBox && this.props.setPdfBox(this); - - 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)); } } - - componentWillUnmount() { - this._reactionDisposer && this._reactionDisposer(); - } - - 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(); - } - - setPdfViewer = (pdfViewer: PDFViewer) => { - this._pdfViewer = pdfViewer; - } - - @action - public BackPage() { - this._pdfViewer!.pdfViewer.scrollPageIntoView({ pageNumber: Math.max(1, NumCast(this.props.Document.curPage) - 1) }); - } - - @action - public GotoPage = (p: number) => { - this._pdfViewer!.pdfViewer.scrollPageIntoView({ pageNumber: p }); - } - - @action - public ForwardPage() { - this._pdfViewer!.pdfViewer.scrollPageIntoView({ pageNumber: Math.min(this._pdfViewer!.pdfViewer.pagesCount, NumCast(this.props.Document.curPage) + 1) }); + loaded = (nw: number, nh: number, np: number) => { + this.dataDoc.numPages = np; + if (!this.Document.nativeWidth || !this.Document.nativeHeight || !this.Document.scrollHeight) { + let oldaspect = (this.Document.nativeHeight || 0) / (this.Document.nativeWidth || 1); + this.Document.nativeWidth = nw; + this.Document.nativeHeight = this.Document.nativeHeight ? nw * oldaspect : nh; + this.Document.height = this.Document[WidthSym]() * (nh / nw); + } } - @action - setPanY = (y: number) => { - this.Document.panY = y; - } + 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 gotoPage = (p: number) => { this._pdfViewer!.gotoPage(p); } + public forwardPage() { this._pdfViewer!.gotoPage(NumCast(this.props.Document.curPage) + 1); } + @undoBatch @action private applyFilter = () => { let scriptText = this._scriptValue ? this._scriptValue : @@ -101,10 +76,6 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen this.props.Document.filterScript = ScriptField.MakeFunction(scriptText); } - scrollTo = (y: number) => { - - } - private resetFilters = () => { this._keyValue = this._valueValue = this._scriptValue = ""; this._keyRef.current && (this._keyRef.current.value = ""); @@ -116,51 +87,38 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen private newValueChange = (e: React.ChangeEvent<HTMLInputElement>) => this._valueValue = e.currentTarget.value; private newScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => this._scriptValue = e.currentTarget.value; - _isChildActive = false; - whenActiveChanged = (isActive: boolean) => { - this._isChildActive = isActive; - this.props.whenActiveChanged(isActive); - } - active = () => { - return this.props.isSelected() || this._isChildActive || this.props.renderDepth === 0; - } + whenActiveChanged = (isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive); + active = () => this.props.isSelected() || this._isChildActive || this.props.renderDepth === 0; + setPdfViewer = (pdfViewer: PDFViewer) => { this._pdfViewer = pdfViewer; } searchStringChanged = (e: React.ChangeEvent<HTMLInputElement>) => this._searchString = e.currentTarget.value; - @observable _pageControls = false; + settingsPanel() { - trace(); let pageBtns = <> <button className="pdfBox-overlayButton-iconCont" key="back" title="Page Back" onPointerDown={(e) => e.stopPropagation()} - onClick={() => this.BackPage()} + onClick={() => this.backPage()} style={{ left: 50, top: 5, height: "30px", position: "absolute", pointerEvents: "all" }}> <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()} + onClick={() => this.forwardPage()} style={{ left: 80, top: 5, height: "30px", position: "absolute", pointerEvents: "all" }}> <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-right"} size="sm" /> </button> </> return !this.props.active() ? (null) : - (<div className="pdfBox-ui" onKeyDown={e => e.keyCode === KeyCodes.BACKSPACE || e.keyCode === KeyCodes.DELETE ? e.stopPropagation() : true} style={{ display: this.active() ? "flex" : "none" }}> - <div className="pdfBox-overlayCont" key="cont" onPointerDown={(e) => e.stopPropagation()} - style={{ bottom: 0, left: `${this._searching ? 0 : 100}%` }}> + (<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" }}> + <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-overlaySearchBar" placeholder="Search" onChange={this.searchStringChanged} - onKeyDown={e => e.keyCode === KeyCodes.ENTER ? this.search(this._searchString, !e.shiftKey) : e.keyCode === KeyCodes.BACKSPACE ? e.stopPropagation() : true} /> + <input className="pdfBox-searchBar" placeholder="Search" 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-overlayButton-iconCont" title="Previous Annotation" - onClick={e => { e.stopPropagation(); this.prevAnnotation(); }} - onPointerDown={(e) => e.stopPropagation()} - style={{ left: 50, top: 5, height: "30px", position: "absolute" }}> + <button className="pdfBox-prevIcon " title="Previous Annotation" onClick={e => this.prevAnnotation()} > <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-up"} size="sm" /> </button> - <button className="pdfBox-overlayButton-iconCont" title="Next Annotation" - onClick={e => { e.stopPropagation(); this.nextAnnotation(); }} - onPointerDown={(e) => e.stopPropagation()} - style={{ left: 20, top: 5, height: "30px", position: "absolute" }}> + <button className="pdfBox-nextIcon" title="Next Annotation" onClick={e => this.nextAnnotation()} > <FontAwesomeIcon style={{ color: "white" }} icon={"arrow-down"} size="sm" /> </button> </div> @@ -170,7 +128,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> - <span contentEditable={true} onInput={e => this.GotoPage(Number(e.currentTarget.textContent))} + <span contentEditable={true} onInput={e => this.gotoPage(Number(e.currentTarget.textContent))} style={{ left: 20, top: 5, height: "30px", width: "30px", position: "absolute", pointerEvents: "all" }} onClick={action(() => this._pageControls = !this._pageControls)}> {`${NumCast(this.props.Document.curPage)}`} @@ -209,16 +167,6 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen </div>); } - loaded = (nw: number, nh: number, np: number) => { - this.dataDoc.numPages = np; - if (!this.Document.nativeWidth || !this.Document.nativeHeight || !this.Document.scrollHeight) { - let oldaspect = (this.Document.nativeHeight || 0) / (this.Document.nativeWidth || 1); - this.Document.nativeWidth = nw; - this.Document.nativeHeight = this.Document.nativeHeight ? nw * oldaspect : nh; - this.Document.height = this.Document[WidthSym]() * (nh / nw); - } - } - render() { const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField); let classname = "pdfBox-cont" + (InkingControl.Instance.selectedTool || !this.active ? "" : "-interactive"); @@ -226,15 +174,15 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen <div>{`pdf, ${this.dataDoc[this.props.fieldKey]}, not found`}</div> : <div className={classname} onWheel={(e: React.WheelEvent) => e.stopPropagation()} onPointerDown={(e: React.PointerEvent) => { let hit = document.elementFromPoint(e.clientX, e.clientY); - if (hit && hit.localName === "span") { + if (hit && hit.localName === "span" && this.props.isSelected()) { e.button === 0 && e.stopPropagation(); } }}> - <PDFViewer {...this.props} pdf={this._pdf} url={pdfUrl.url.pathname} active={this.props.active} scrollTo={this.scrollTo} loaded={this.loaded} + <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} + addDocTab={this.props.addDocTab} GoToPage={this.gotoPage} pinToPres={this.props.pinToPres} addDocument={this.props.addDocument} ScreenToLocalTransform={this.props.ScreenToLocalTransform} isSelected={this.props.isSelected} whenActiveChanged={this.whenActiveChanged} diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 848f1ddcd..427da1d9b 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -40,7 +40,6 @@ interface IViewerProps { renderDepth: number; isSelected: () => boolean; loaded: (nw: number, nh: number, np: number) => void; - scrollTo: (y: number) => void; active: () => boolean; GoToPage?: (n: number) => void; addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; @@ -263,6 +262,11 @@ export class PDFViewer extends React.Component<IViewerProps> { } @action + gotoPage = (p: number) => { + this.pdfViewer.scrollPageIntoView({ pageNumber: Math.min(Math.max(1, p), this._pageSizes.length) }); + } + + @action scrollToAnnotation = (scrollToAnnotation: Doc) => { this.allAnnotations.forEach(d => Doc.UnBrushDoc(d)); let windowHgt = this.props.PanelHeight() / this.props.ContentScaling(); |