diff options
Diffstat (limited to 'src/client/views/pdf/PDFViewer.tsx')
-rw-r--r-- | src/client/views/pdf/PDFViewer.tsx | 158 |
1 files changed, 79 insertions, 79 deletions
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 3c052d10b..38890410c 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -1,18 +1,16 @@ -import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from "mobx"; +import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, trace } from "mobx"; import { observer } from "mobx-react"; import * as Pdfjs from "pdfjs-dist"; import "pdfjs-dist/web/pdf_viewer.css"; -import { Doc, DocListCast, Field, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; +import { Doc, DocListCast, Field, HeightSym, Opt } from "../../../fields/Doc"; import { Id } from "../../../fields/FieldSymbols"; import { InkTool } from "../../../fields/InkField"; -import { Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types"; +import { Cast, NumCast, StrCast } from "../../../fields/Types"; import { PdfField } from "../../../fields/URLField"; import { TraceMobx } from "../../../fields/util"; import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, OmitKeys, smoothScroll, Utils } from "../../../Utils"; import { DocUtils } from "../../documents/Documents"; -import { Networking } from "../../Network"; import { CurrentUserUtils } from "../../util/CurrentUserUtils"; -import { CompiledScript, CompileScript } from "../../util/Scripting"; import { SelectionManager } from "../../util/SelectionManager"; import { SharingManager } from "../../util/SharingManager"; import { SnappingManager } from "../../util/SnappingManager"; @@ -59,11 +57,9 @@ export class PDFViewer extends React.Component<IViewerProps> { static _annotationStyle: any = addStyleSheet(); @observable private _pageSizes: { width: number, height: number }[] = []; @observable private _savedAnnotations = new ObservableMap<number, HTMLDivElement[]>(); - @observable private _script: CompiledScript = CompileScript("return true") as CompiledScript; @observable private _marqueeing: number[] | undefined; @observable private _textSelecting = true; @observable private _showWaiting = true; - @observable private _showCover = false; @observable private _zoomed = 1; @observable private _overlayAnnoInfo: Opt<Doc>; @observable private Index: number = -1; @@ -79,14 +75,13 @@ export class PDFViewer extends React.Component<IViewerProps> { private _selectionText: string = ""; private _downX: number = 0; private _downY: number = 0; - private _coverPath: any; private _lastSearch = false; private _viewerIsSetup = false; private _ignoreScroll = false; private _initialScroll: Opt<number>; private _forcedScroll = true; - + @observable isAnnotating = false; // key where data is stored @computed get allAnnotations() { return DocUtils.FilterDocs(DocListCast(this.props.dataDoc[this.props.fieldKey + "-annotations"]), this.props.docFilters(), this.props.docRangeFilters(), undefined); @@ -108,13 +103,11 @@ export class PDFViewer extends React.Component<IViewerProps> { if (pathComponents.length) { params.subtree = `${pathComponents.join("/")}/`; } - this._coverPath = href.startsWith(window.location.origin) ? await Networking.PostToServer("/thumbnail", params) : { width: 100, height: 100, path: "" }; } else { const params: any = { coreFilename: relative.split("/")[relative.split("/").length - 1], pageNum: Math.min(this.props.pdf.numPages, Math.max(1, NumCast(this.props.Document._curPage, 1))), }; - this._coverPath = "http://cs.brown.edu/~bcz/face.gif";//href.startsWith(window.location.origin) ? await Networking.PostToServer("/thumbnail", params) : { width: 100, height: 100, path: "" }; } runInAction(() => this._showWaiting = true); this.props.startupLive && this.setupPdfJsViewer(); @@ -207,17 +200,6 @@ export class PDFViewer extends React.Component<IViewerProps> { this.props.setPdfViewer(this); await this.initialLoad(); - this._disposers.filterScript = reaction( - () => ScriptCast(this.props.Document.filterScript), - action(scriptField => { - const oldScript = this._script.originalScript; - this._script = scriptField?.script.compiled ? scriptField.script : CompileScript("return true") as CompiledScript; - if (this._script.originalScript !== oldScript) { - this.Index = -1; - } - }), - { fireImmediately: true }); - this.createPdfViewer(); } @@ -232,7 +214,7 @@ export class PDFViewer extends React.Component<IViewerProps> { () => Math.abs(NumCast(this.props.Document._scrollTop)), (pos) => { if (!this._ignoreScroll) { - (this._showCover || this._showWaiting) && this.setupPdfJsViewer(); + this._showWaiting && this.setupPdfJsViewer(); const viewTrans = quickScroll ?? StrCast(this.props.Document._viewTransition); const durationMiliStr = viewTrans.match(/([0-9]*)ms/); const durationSecStr = viewTrans.match(/([0-9.]*)s/); @@ -377,6 +359,7 @@ export class PDFViewer extends React.Component<IViewerProps> { this.props.select(false); MarqueeAnnotator.clearAnnotations(this._savedAnnotations); this._marqueeing = [e.clientX, e.clientY]; + this.isAnnotating = true; if (e.target && ((e.target as any).className.includes("endOfContent") || ((e.target as any).parentElement.className !== "textLayer"))) { this._textSelecting = false; document.addEventListener("pointermove", this.onSelectMove); // need this to prevent document from being dragged if stopPropagation doesn't get called @@ -393,6 +376,7 @@ export class PDFViewer extends React.Component<IViewerProps> { @action finishMarquee = (x?: number, y?: number) => { + this.isAnnotating = false; this._marqueeing = undefined; this._textSelecting = true; document.removeEventListener("pointermove", this.onSelectMove); @@ -402,6 +386,7 @@ export class PDFViewer extends React.Component<IViewerProps> { @action onSelectEnd = (e: PointerEvent): void => { + this.isAnnotating = false; clearStyleSheetRules(PDFViewer._annotationStyle); this.props.select(false); document.removeEventListener("pointermove", this.onSelectMove); @@ -459,20 +444,6 @@ export class PDFViewer extends React.Component<IViewerProps> { setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean) => void) => this._setPreviewCursor = func; - getCoverImage = () => { - if (!this.props.Document[HeightSym]() || !Doc.NativeHeight(this.props.Document)) { - setTimeout((() => { - this.props.Document._height = this.props.Document[WidthSym]() * this._coverPath.height / this._coverPath.width; - Doc.SetNativeWidth(this.props.Document, (Doc.NativeWidth(this.props.Document) || 0) * this._coverPath.height / this._coverPath.width); - }).bind(this), 0); - } - const nativeWidth = Doc.NativeWidth(this.props.Document); - const nativeHeight = Doc.NativeHeight(this.props.Document); - const resolved = Utils.prepend(this._coverPath.path); - return <img key={resolved} src={resolved} onError={action(() => this._coverPath.path = "http://www.cs.brown.edu/~bcz/face.gif")} onLoad={action(() => this._showWaiting = false)} - style={{ position: "absolute", display: "inline-block", top: 0, left: 0, width: `${nativeWidth}px`, height: `${nativeHeight}px` }} />; - } - @action onZoomWheel = (e: React.WheelEvent) => { if (this.props.isContentActive(true)) { @@ -495,7 +466,7 @@ export class PDFViewer extends React.Component<IViewerProps> { } @computed get overlayInfo() { - return !this._overlayAnnoInfo || this._overlayAnnoInfo.author === Doc.CurrentUserEmail ? (null) : + return !this._overlayAnnoInfo ? (null) : <div className="pdfViewerDash-overlayAnno" style={{ top: NumCast(this._overlayAnnoInfo.y), left: NumCast(this._overlayAnnoInfo.x) }}> <div className="pdfViewerDash-overlayAnno" style={{ right: -50, background: SharingManager.Instance.users.find(users => users.user.email === this._overlayAnnoInfo!.author)?.userColor }}> {this._overlayAnnoInfo.author + " " + Field.toString(this._overlayAnnoInfo.creationDate as Field)} @@ -517,41 +488,76 @@ export class PDFViewer extends React.Component<IViewerProps> { } return this.props.styleProvider?.(doc, props, property); } + renderAnnotations = (docFilters?: () => string[]) => + <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit} + isAnnotationOverlay={true} + fieldKey={this.props.fieldKey + "-annotations"} + setPreviewCursor={this.setPreviewCursor} + PanelHeight={this.panelHeight} + PanelWidth={this.panelWidth} + dropAction={"alias"} + select={emptyFunction} + ContentScaling={this.contentZoom} + bringToFront={emptyFunction} + docFilters={docFilters || this.basicFilter} + styleProvider={this.childStyleProvider} + dontRenderDocuments={docFilters ? false : true} + CollectionView={undefined} + ScreenToLocalTransform={this.overlayTransform} + renderDepth={this.props.renderDepth + 1} />; + + @computed get overlayLayerClickableAnnotations() { + return SnappingManager.GetIsDragging() ? (null) : this.renderAnnotations(); + } + @computed get overlayLayerOpaqueAnnotations() { + trace(); + return <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit} + isAnnotationOverlay={true} + fieldKey={this.props.fieldKey + "-annotations"} + setPreviewCursor={this.setPreviewCursor} + PanelHeight={this.panelHeight} + PanelWidth={this.panelWidth} + dropAction={"alias"} + select={emptyFunction} + ContentScaling={this.contentZoom} + bringToFront={emptyFunction} + docFilters={this.opaqueFilter} + styleProvider={this.childStyleProvider} + dontRenderDocuments={false} + CollectionView={undefined} + ScreenToLocalTransform={this.overlayTransform} + renderDepth={this.props.renderDepth + 1} /> + } + @computed get overlayLayerTransparentAnnotations() { + trace(); + return <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit} + isAnnotationOverlay={true} + fieldKey={this.props.fieldKey + "-annotations"} + setPreviewCursor={this.setPreviewCursor} + PanelHeight={this.panelHeight} + PanelWidth={this.panelWidth} + dropAction={"alias"} + select={emptyFunction} + ContentScaling={this.contentZoom} + bringToFront={emptyFunction} + docFilters={this.transparentFilter} + styleProvider={this.childStyleProvider} + dontRenderDocuments={false} + CollectionView={undefined} + ScreenToLocalTransform={this.overlayTransform} + renderDepth={this.props.renderDepth + 1} /> + } @computed get overlayLayer() { - const renderAnnotations = (docFilters?: () => string[]) => - <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit} - isAnnotationOverlay={true} - fieldKey={this.props.fieldKey + "-annotations"} - setPreviewCursor={this.setPreviewCursor} - PanelHeight={this.panelHeight} - PanelWidth={this.panelWidth} - dropAction={"alias"} - select={emptyFunction} - ContentScaling={this.contentZoom} - bringToFront={emptyFunction} - docFilters={docFilters || this.basicFilter} - styleProvider={this.childStyleProvider} - dontRenderDocuments={docFilters ? false : true} - CollectionView={undefined} - ScreenToLocalTransform={this.overlayTransform} - renderDepth={this.props.renderDepth + 1} />; - return <div> - <div className={`pdfViewerDash-overlay${CurrentUserUtils.SelectedTool !== InkTool.None || SnappingManager.GetIsDragging() ? "-inking" : ""}`} - style={{ - pointerEvents: SnappingManager.GetIsDragging() ? "all" : undefined, - mixBlendMode: "multiply", - transform: `scale(${this._zoomed})` - }}> - {renderAnnotations(this.transparentFilter)} + return <div className="pdfViewerDash-overlay" style={{ + transform: `scale(${this._zoomed})`, + pointerEvents: CurrentUserUtils.SelectedTool !== InkTool.None || SnappingManager.GetIsDragging() ? "all" : "none", + }} > + <div className="pdfViewerDash-overlay" key="muliplied" style={{ mixBlendMode: "multiply", }}> + {this.overlayLayerTransparentAnnotations} </div> - <div className={`pdfViewerDash-overlay${CurrentUserUtils.SelectedTool !== InkTool.None || SnappingManager.GetIsDragging() ? "-inking" : ""}`} - style={{ - pointerEvents: SnappingManager.GetIsDragging() ? "all" : undefined, - mixBlendMode: this.allAnnotations.some(anno => anno.mixBlendMode) ? "hard-light" : undefined, - transform: `scale(${this._zoomed})` - }}> - {renderAnnotations(this.opaqueFilter)} - {SnappingManager.GetIsDragging() ? (null) : renderAnnotations()} + <div className="pdfViewerDash-overlay" key="blended" style={{ mixBlendMode: this.allAnnotations.some(anno => anno.mixBlendMode) ? "hard-light" : undefined, }}> + {this.overlayLayerOpaqueAnnotations} + {this.overlayLayerClickableAnnotations} </div> </div>; } @@ -559,12 +565,6 @@ export class PDFViewer extends React.Component<IViewerProps> { return <div className={"pdfViewerDash-text" + (this.props.pointerEvents !== "none" && this._textSelecting && this.props.isContentActive() ? "-selected" : "")} ref={this._viewer} />; } @computed get contentScaling() { return this.props.ContentScaling?.() || 1; } - @computed get standinViews() { - return <> - {this._showCover ? this.getCoverImage() : (null)} - {this._showWaiting ? <img className="pdfViewerDash-waiting" key="waiting" src={"/assets/loading.gif"} /> : (null)} - </>; - } contentZoom = () => this._zoomed; savedAnnotations = () => this._savedAnnotations; render() { @@ -581,7 +581,7 @@ export class PDFViewer extends React.Component<IViewerProps> { {this.annotationLayer} {this.overlayLayer} {this.overlayInfo} - {this.standinViews} + {this._showWaiting ? <img className="pdfViewerDash-waiting" src={"/assets/loading.gif"} /> : (null)} {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? (null) : <MarqueeAnnotator rootDoc={this.props.rootDoc} getPageFromScroll={this.getPageFromScroll} @@ -594,7 +594,7 @@ export class PDFViewer extends React.Component<IViewerProps> { savedAnnotations={this.savedAnnotations} annotationLayer={this._annotationLayer.current} mainCont={this._mainCont.current} - anchorMenuCrop={this.crop} + anchorMenuCrop={this._textSelecting ? undefined : this.crop} />} </div> </div>; |