diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/nodes/WebBox.scss | 15 | ||||
-rw-r--r-- | src/client/views/nodes/WebBox.tsx | 109 | ||||
-rw-r--r-- | src/client/views/pdf/PDFViewer.tsx | 2 | ||||
-rw-r--r-- | src/new_fields/documentSchemas.ts | 2 |
4 files changed, 87 insertions, 41 deletions
diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss index b41687c11..3c82e5240 100644 --- a/src/client/views/nodes/WebBox.scss +++ b/src/client/views/nodes/WebBox.scss @@ -3,6 +3,21 @@ .webBox-container, .webBox-container-dragging { transform-origin: top left; + .webBox-outerContent { + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + overflow: auto; + pointer-events: all; + .webBox-innerContent { + width:100%; + } + } + div.webBox-outerContent::-webkit-scrollbar-thumb { + display:none; + } } .webBox-cont, .webBox-cont-dragging { diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 55ad7eb0f..b61d38d62 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -1,6 +1,6 @@ import { library } from "@fortawesome/fontawesome-svg-core"; import { faStickyNote } from '@fortawesome/free-solid-svg-icons'; -import { action, computed, observable } from "mobx"; +import { action, computed, observable, trace } from "mobx"; import { observer } from "mobx-react"; import { Doc, FieldResult } from "../../../new_fields/Doc"; import { documentSchema } from "../../../new_fields/documentSchemas"; @@ -18,7 +18,6 @@ import { ViewBoxAnnotatableComponent } from "../DocComponent"; import { DocumentDecorations } from "../DocumentDecorations"; import { InkingControl } from "../InkingControl"; import { FieldView, FieldViewProps } from './FieldView'; -import { KeyValueBox } from "./KeyValueBox"; import "./WebBox.scss"; import React = require("react"); import * as WebRequest from 'web-request'; @@ -26,7 +25,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView"; const htmlToText = require("html-to-text"); - library.add(faStickyNote); type WebDocument = makeInterface<[typeof documentSchema]>; @@ -40,19 +38,38 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum @observable private url: string = "hello"; private _longPressSecondsHack?: NodeJS.Timeout; + private _outerRef = React.createRef<HTMLDivElement>(); private _iframeRef = React.createRef<HTMLIFrameElement>(); private _iframeIndicatorRef = React.createRef<HTMLDivElement>(); private _iframeDragRef = React.createRef<HTMLDivElement>(); @observable private _pressX: number = 0; @observable private _pressY: number = 0; - + private _scrollTop = 0; + private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean) => void); + + iframeLoaded = action((e: any) => { + this._iframeRef.current!.contentDocument?.addEventListener('pointerdown', this.iframedown, false); + this._iframeRef.current!.contentDocument?.addEventListener('scroll', this.iframeScrolled, false); + this.layoutDoc.scrollHeight = this._iframeRef.current!.contentDocument?.children?.[0].scrollHeight || 1000; + this._iframeRef.current!.contentDocument!.children[0].scrollTop = NumCast(this.layoutDoc.scrollTop); + }); + setPreviewCursor = (func?: (x: number, y: number, drag: boolean) => void) => this._setPreviewCursor = func; + iframedown = (e: PointerEvent) => { + this._setPreviewCursor?.(e.screenX, e.screenY, false); + } + iframeScrolled = (e: any) => { + const scroll = (e.target as any)?.children?.[0].scrollTop; + this.layoutDoc.scrollTop = this._outerRef.current!.scrollTop = this._scrollTop = scroll; + } async componentDidMount() { this.setURL(); + this._iframeRef.current!.setAttribute("enable-annotation", "true"); + document.addEventListener("pointerup", this.onLongPressUp); document.addEventListener("pointermove", this.onLongPressMove); - const field = Cast(this.props.Document[this.props.fieldKey], WebField); + const field = Cast(this.rootDoc[this.props.fieldKey], WebField); if (field?.url.href.indexOf("youtube") !== -1) { const youtubeaspect = 400 / 315; const nativeWidth = NumCast(this.layoutDoc._nativeWidth); @@ -66,12 +83,13 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum const result = await WebRequest.get(Utils.CorsProxy(field.url.href)); this.dataDoc.text = htmlToText.fromString(result.content); } - } componentWillUnmount() { document.removeEventListener("pointerup", this.onLongPressUp); document.removeEventListener("pointermove", this.onLongPressMove); + this._iframeRef.current!.contentDocument?.removeEventListener('pointerdown', this.iframedown); + this._iframeRef.current!.contentDocument?.removeEventListener('scroll', this.iframeScrolled); } @action @@ -101,20 +119,20 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum switchToText = () => { let url: string = ""; - const field = Cast(this.props.Document[this.props.fieldKey], WebField); + const field = Cast(this.rootDoc[this.props.fieldKey], WebField); if (field) url = field.url.href; const newBox = Docs.Create.TextDocument(url, { - x: NumCast(this.props.Document.x), - y: NumCast(this.props.Document.y), + x: NumCast(this.rootDoc.x), + y: NumCast(this.rootDoc.y), title: url, _width: 200, _height: 70, }); SelectionManager.SelectedDocuments().map(dv => { - dv.props.addDocument && dv.props.addDocument(newBox); - dv.props.removeDocument && dv.props.removeDocument(dv.props.Document); + dv.props.addDocument?.(newBox); + dv.props.removeDocument?.(dv.rootDoc); }); Doc.BrushDoc(newBox); @@ -293,7 +311,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum if (field instanceof HtmlField) { view = <span id="webBox-htmlSpan" dangerouslySetInnerHTML={{ __html: field.html }} />; } else if (field instanceof WebField) { - view = <iframe ref={this._iframeRef} src={Utils.CorsProxy(field.url.href)} style={{ position: "absolute", width: "100%", height: "100%", top: 0 }} />; + view = <iframe ref={this._iframeRef} onLoad={this.iframeLoaded} src={Utils.CorsProxy(field.url.href)} style={{ position: "absolute", width: "100%", height: "100%", top: 0 }} />; } else { view = <iframe ref={this._iframeRef} src={"https://crossorigin.me/https://cs.brown.edu"} style={{ position: "absolute", width: "100%", height: "100%", top: 0 }} />; } @@ -303,14 +321,13 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum {view} </div>; - const decInteracting = DocumentDecorations.Instance && DocumentDecorations.Instance.Interacting; + const decInteracting = DocumentDecorations.Instance?.Interacting; const frozen = !this.props.isSelected() || decInteracting; - const classname = "webBox-cont" + (this.props.isSelected() && InkingControl.Instance.selectedTool === InkTool.None && !decInteracting ? "-interactive" : ""); return ( <> - <div className={classname} > + <div className={"webBox-cont" + (this.props.isSelected() && InkingControl.Instance.selectedTool === InkTool.None && !decInteracting ? "-interactive" : "")} > {content} </div> {!frozen ? (null) : @@ -322,37 +339,49 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum </div>} </>); } + scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.props.Document.scrollTop)) render() { - const dragging = "";//</div>!SelectionManager.GetIsDragging() ? "" : "-dragging"; - return (<div className={`webBox-container${dragging}`} + return (<div className={`webBox-container`} style={{ transform: `scale(${this.props.ContentScaling()})`, width: `${100 / this.props.ContentScaling()}%`, height: `${100 / this.props.ContentScaling()}%`, - pointerEvents: this.props.Document.isBackground ? "none" : undefined + pointerEvents: this.layoutDoc.isBackground ? "none" : undefined }} > - <CollectionFreeFormView {...this.props} - PanelHeight={this.props.PanelHeight} - PanelWidth={this.props.PanelWidth} - annotationsKey={this.annotationKey} - NativeHeight={returnZero} - NativeWidth={returnZero} - focus={this.props.focus} - isSelected={this.props.isSelected} - isAnnotationOverlay={true} - select={emptyFunction} - active={this.active} - ContentScaling={returnOne} - whenActiveChanged={this.whenActiveChanged} - removeDocument={this.removeDocument} - moveDocument={this.moveDocument} - addDocument={this.addDocument} - CollectionView={undefined} - ScreenToLocalTransform={this.props.ScreenToLocalTransform} - renderDepth={this.props.renderDepth + 1} - ContainingCollectionDoc={this.props.ContainingCollectionDoc}> - {() => [this.content]} - </CollectionFreeFormView> + {this.content} + <div className={"webBox-outerContent"} ref={this._outerRef} + onWheel={e => e.stopPropagation()} + onScroll={e => { + if (this._iframeRef.current!.contentDocument!.children[0].scrollTop !== this._outerRef.current!.scrollTop) { + this._iframeRef.current!.contentDocument!.children[0].scrollTop = this._outerRef.current!.scrollTop; + } + //this._outerRef.current!.scrollTop !== this._scrollTop && (this._outerRef.current!.scrollTop = this._scrollTop) + }}> + <div className={"webBox-innerContent"} style={{ height: NumCast(this.layoutDoc.scrollHeight) }}> + <CollectionFreeFormView {...this.props} + PanelHeight={this.props.PanelHeight} + PanelWidth={this.props.PanelWidth} + annotationsKey={this.annotationKey} + NativeHeight={returnZero} + NativeWidth={returnZero} + focus={this.props.focus} + setPreviewCursor={this.setPreviewCursor} + isSelected={this.props.isSelected} + isAnnotationOverlay={true} + select={emptyFunction} + active={this.active} + ContentScaling={returnOne} + whenActiveChanged={this.whenActiveChanged} + removeDocument={this.removeDocument} + moveDocument={this.moveDocument} + addDocument={this.addDocument} + CollectionView={undefined} + ScreenToLocalTransform={this.scrollXf} + renderDepth={this.props.renderDepth + 1} + ContainingCollectionDoc={this.props.ContainingCollectionDoc}> + </CollectionFreeFormView> + </div> + </div> </div >); } }
\ No newline at end of file diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index c49e6512a..948d2300d 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -419,7 +419,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu addStyleSheetRule(PDFViewer._annotationStyle, "pdfAnnotation", { "pointer-events": "none" }); if ((this.Document.scale || 1) !== 1) return; if ((e.button !== 0 || e.altKey) && this.active(true)) { - this._setPreviewCursor && this._setPreviewCursor(e.clientX, e.clientY, true); + this._setPreviewCursor?.(e.clientX, e.clientY, true); //e.stopPropagation(); } this._marqueeing = false; diff --git a/src/new_fields/documentSchemas.ts b/src/new_fields/documentSchemas.ts index bc63e9df8..61b185e5c 100644 --- a/src/new_fields/documentSchemas.ts +++ b/src/new_fields/documentSchemas.ts @@ -57,6 +57,8 @@ export const documentSchema = createSchema({ isLinkButton: "boolean", // whether document functions as a link follow button to follow the first link on the document when clicked ignoreClick: "boolean", // whether documents ignores input clicks (but does not ignore manipulation and other events) scrollToLinkID: "string", // id of link being traversed. allows this doc to scroll/highlight/etc its link anchor. scrollToLinkID should be set to undefined by this doc after it sets up its scroll,etc. + scrollY: "number", // "command" to scroll a document to a position on load (the value will be reset to 0 after that ) + scrollTop: "number", // scroll position of a scrollable document (pdf, text, web) strokeWidth: "number", fontSize: "string", fitToBox: "boolean", // whether freeform view contents should be zoomed/panned to fill the area of the document view |