From 88a8ae38f6e9be6a1c51783d68864c6cc47ba8e6 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 3 Jun 2020 17:50:41 -0400
Subject: cleaned up internalDrop code.  fixed drop to work with ACLs that
 don't permit drop

---
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 128 ++++++++++-----------
 1 file changed, 62 insertions(+), 66 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index c753a703d..a8eef6875 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -46,7 +46,6 @@ import React = require("react");
 import { CollectionViewType } from "../CollectionView";
 import { Timeline } from "../../animationtimeline/Timeline";
 import { SnappingManager } from "../../../util/SnappingManager";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 
 library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard, faFileUpload);
 
@@ -188,79 +187,76 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         return this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => pair.layout);
     }
 
+    onExternalDrop = (e: React.DragEvent) => {
+        return (pt => super.onExternalDrop(e, { x: pt[0], y: pt[1] }))(this.getTransform().transformPoint(e.pageX, e.pageY));
+    }
+
+    @undoBatch
+    @action
+    internalDocDrop(e: Event, de: DragManager.DropEvent, docDragData: DragManager.DocumentDragData, xp: number, yp: number) {
+        if (!super.onInternalDrop(e, de)) return false;
+        const [xpo, ypo] = this.getTransformOverlay().transformPoint(de.x, de.y);
+        const z = NumCast(docDragData.droppedDocuments[0].z);
+        const x = (z ? xpo : xp) - docDragData.offset[0];
+        const y = (z ? ypo : yp) - docDragData.offset[1];
+        const zsorted = this.childLayoutPairs.map(pair => pair.layout).slice().sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex));
+        zsorted.forEach((doc, index) => doc.zIndex = index + 1);
+        const dropPos = [NumCast(docDragData.droppedDocuments[0].x), NumCast(docDragData.droppedDocuments[0].y)];
+        for (let i = 0; i < docDragData.droppedDocuments.length; i++) {
+            const d = docDragData.droppedDocuments[i];
+            const layoutDoc = Doc.Layout(d);
+            if (this.Document.currentFrame !== undefined && !this.props.isAnnotationOverlay) {
+                const vals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000));
+                CollectionFreeFormDocumentView.setValues(this.Document.currentFrame, d, x + vals.x - dropPos[0], y + vals.y - dropPos[1], vals.opacity);
+            } else {
+                d.x = x + NumCast(d.x) - dropPos[0];
+                d.y = y + NumCast(d.y) - dropPos[1];
+            }
+            const nd = [NumCast(layoutDoc._nativeWidth), NumCast(layoutDoc._nativeHeight)];
+            layoutDoc._width = NumCast(layoutDoc._width, 300);
+            layoutDoc._height = NumCast(layoutDoc._height, nd[0] && nd[1] ? nd[1] / nd[0] * NumCast(layoutDoc._width) : 300);
+            d.isBackground === undefined && (d.zIndex = zsorted.length + 1 + i); // bringToFront
+        }
+
+        (docDragData.droppedDocuments.length === 1 || de.shiftKey) && this.updateClusterDocs(docDragData.droppedDocuments);
+        return true;
+    }
+
+    @undoBatch
     @action
-    onExternalDrop = (e: React.DragEvent): Promise<void> => {
-        const pt = this.getTransform().transformPoint(e.pageX, e.pageY);
-        return super.onExternalDrop(e, { x: pt[0], y: pt[1] });
+    internalPdfAnnoDrop(e: Event, annoDragData: DragManager.PdfAnnoDragData, xp: number, yp: number) {
+        const dragDoc = annoDragData.dropDocument;
+        const dropPos = [NumCast(dragDoc.x), NumCast(dragDoc.y)];
+        dragDoc.x = xp - annoDragData.offset[0] + (NumCast(dragDoc.x) - dropPos[0]);
+        dragDoc.y = yp - annoDragData.offset[1] + (NumCast(dragDoc.y) - dropPos[1]);
+        annoDragData.targetContext = this.props.Document; // dropped a PDF annotation, so we need to set the targetContext on the dragData which the PDF view uses at the end of the drop operation
+        this.bringToFront(dragDoc);
+        return true;
     }
 
     @undoBatch
+    @action
+    internalLinkDrop(e: Event, de: DragManager.DropEvent, linkDragData: DragManager.LinkDragData, xp: number, yp: number) {
+        if (linkDragData.linkSourceDocument === this.props.Document) return false;
+        const source = Docs.Create.TextDocument("", { _width: 200, _height: 75, x: xp, y: yp, title: "dropped annotation" });
+        this.props.addDocument(source);
+        linkDragData.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: linkDragData.linkSourceDocument }, "doc annotation"); // TODODO this is where in text links get passed
+        e.stopPropagation();
+        return true;
+    }
+
     @action
     onInternalDrop = (e: Event, de: DragManager.DropEvent) => {
         // if (this.props.Document.isBackground) return false;
-        const xf = this.getTransform();
-        const xfo = this.getTransformOverlay();
-        const [xp, yp] = xf.transformPoint(de.x, de.y);
-        const [xpo, ypo] = xfo.transformPoint(de.x, de.y);
-        const zsorted = this.childLayoutPairs.map(pair => pair.layout).slice().sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex));
-        if (!this.isAnnotationOverlay && de.complete.linkDragData && de.complete.linkDragData.linkSourceDocument !== this.props.Document) {
-            const source = Docs.Create.TextDocument("", { _width: 200, _height: 75, x: xp, y: yp, title: "dropped annotation" });
-            this.props.addDocument(source);
-            (de.complete.linkDragData.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: de.complete.linkDragData.linkSourceDocument },
-                "doc annotation")); // TODODO this is where in text links get passed
-            e.stopPropagation();
+        const [xp, yp] = this.getTransform().transformPoint(de.x, de.y);
+        if (this.isAnnotationOverlay !== true && de.complete.linkDragData)
+            return this.internalLinkDrop(e, de, de.complete.linkDragData, xp, yp);
+        if (de.complete.annoDragData?.dropDocument && super.onInternalDrop(e, de))
+            return this.internalPdfAnnoDrop(e, de.complete.annoDragData, xp, yp);
+        if (de.complete.docDragData?.droppedDocuments.length && this.internalDocDrop(e, de, de.complete.docDragData, xp, yp)) {
             return true;
-        }
-        if (super.onInternalDrop(e, de)) {
-            if (de.complete.docDragData) {
-                if (de.complete.docDragData.droppedDocuments.length) {
-                    const firstDoc = de.complete.docDragData.droppedDocuments[0];
-                    const z = NumCast(firstDoc.z);
-                    const x = (z ? xpo : xp) - de.complete.docDragData.offset[0];
-                    const y = (z ? ypo : yp) - de.complete.docDragData.offset[1];
-                    const dropX = NumCast(firstDoc.x);
-                    const dropY = NumCast(firstDoc.y);
-                    const droppedDocs = de.complete.docDragData.droppedDocuments;
-                    runInAction(() => {
-                        zsorted.forEach((doc, index) => doc.zIndex = index + 1);
-                        for (let i = 0; i < droppedDocs.length; i++) {
-                            const d = droppedDocs[i];
-                            const layoutDoc = Doc.Layout(d);
-                            if (this.Document.currentFrame !== undefined && !this.props.isAnnotationOverlay) {
-                                const vals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000));
-                                CollectionFreeFormDocumentView.setValues(this.Document.currentFrame, d, x + vals.x - dropX, y + vals.y - dropY, vals.opacity);
-                            } else {
-                                d.x = x + NumCast(d.x) - dropX;
-                                d.y = y + NumCast(d.y) - dropY;
-                            }
-                            if (!NumCast(layoutDoc._width)) {
-                                layoutDoc._width = 300;
-                            }
-                            if (!NumCast(layoutDoc._height)) {
-                                const nw = NumCast(layoutDoc._nativeWidth);
-                                const nh = NumCast(layoutDoc._nativeHeight);
-                                layoutDoc._height = nw && nh ? nh / nw * NumCast(layoutDoc._width) : 300;
-                            }
-                            d.isBackground === undefined && (d.zIndex = zsorted.length + 1 + i); // bringToFront
-                        }
-                    });
-
-                    (de.complete.docDragData.droppedDocuments.length === 1 || de.shiftKey) && this.updateClusterDocs(de.complete.docDragData.droppedDocuments);
-                }
-            }
-            else if (de.complete.annoDragData) {
-                if (de.complete.annoDragData.dropDocument) {
-                    const dragDoc = de.complete.annoDragData.dropDocument;
-                    const x = xp - de.complete.annoDragData.offset[0];
-                    const y = yp - de.complete.annoDragData.offset[1];
-                    const dropX = NumCast(dragDoc.x);
-                    const dropY = NumCast(dragDoc.y);
-                    dragDoc.x = x + NumCast(dragDoc.x) - dropX;
-                    dragDoc.y = y + NumCast(dragDoc.y) - dropY;
-                    de.complete.annoDragData.targetContext = this.props.Document; // dropped a PDF annotation, so we need to set the targetContext on the dragData which the PDF view uses at the end of the drop operation
-                    this.bringToFront(dragDoc);
-                }
-            }
+        } else {
+            UndoManager.Undo();
         }
         return false;
     }
-- 
cgit v1.2.3-70-g09d2


From e872414f24edddb31a82738bff10e5b9519d92be Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 4 Jun 2020 11:13:39 -0400
Subject: fixed content fitting of freeform views in treeview.

---
 .../collections/collectionFreeForm/CollectionFreeFormView.tsx    | 9 ++++-----
 src/client/views/collections/collectionFreeForm/MarqueeView.tsx  | 2 +-
 2 files changed, 5 insertions(+), 6 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index a8eef6875..fc5e61026 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -118,10 +118,12 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         this.Document.scale || 1)
 
     @computed get cachedCenteringShiftX(): number {
-        return !this.isAnnotationOverlay ? this.props.PanelWidth() / 2 / this.parentScaling / this.contentScaling : 0;  // shift so pan position is at center of window for non-overlay collections
+        const scaling = this.fitToContent ? 1 : this.contentScaling;
+        return !this.isAnnotationOverlay ? this.props.PanelWidth() / 2 / this.parentScaling / scaling : 0;  // shift so pan position is at center of window for non-overlay collections
     }
     @computed get cachedCenteringShiftY(): number {
-        return !this.isAnnotationOverlay ? this.props.PanelHeight() / 2 / this.parentScaling / this.contentScaling : 0;// shift so pan position is at center of window for non-overlay collections
+        const scaling = this.fitToContent ? 1 : this.contentScaling;
+        return !this.isAnnotationOverlay ? this.props.PanelHeight() / 2 / this.parentScaling / scaling : 0;// shift so pan position is at center of window for non-overlay collections
     }
     @computed get cachedGetLocalTransform(): Transform {
         return Transform.Identity().scale(1 / this.zoomScaling()).translate(this.panX(), this.panY());
@@ -1342,7 +1344,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             <CollectionFreeFormViewPannableContents
                 centeringShiftX={this.centeringShiftX}
                 centeringShiftY={this.centeringShiftY}
-                shifted={!this.nativeHeight && !this.isAnnotationOverlay}
                 easing={this.easing}
                 transition={Cast(this.layoutDoc.transition, "string", null)}
                 viewDefDivClick={this.props.viewDefDivClick}
@@ -1428,7 +1429,6 @@ interface CollectionFreeFormViewPannableContentsProps {
     easing: () => boolean;
     viewDefDivClick?: ScriptField;
     children: () => JSX.Element[];
-    shifted: boolean;
     transition?: string;
 }
 
@@ -1443,7 +1443,6 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF
         const zoom = this.props.zoomScaling();
         return <div className={freeformclass}
             style={{
-                width: this.props.shifted ? 0 : undefined, height: this.props.shifted ? 0 : undefined,
                 transform: `translate(${cenx}px, ${ceny}px) scale(${zoom}) translate(${panx}px, ${pany}px)`,
                 transition: this.props.transition
             }}>
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index cdfeeaa6b..46804c848 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -607,7 +607,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
 
     @computed
     get marqueeDiv() {
-        const p: [number, number] = this._visible ? this.props.getContainerTransform().transformPoint(this._downX < this._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY) : [0, 0];
+        const p = this._visible ? this.props.getContainerTransform().transformPoint(this._downX < this._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY) : [0, 0];
         const v = this.props.getContainerTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY);
         /**
          * @RE - The commented out span below
-- 
cgit v1.2.3-70-g09d2


From cdc9c7e293a656573d49c4265b5867e34e8db7c8 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Fri, 5 Jun 2020 18:30:56 -0400
Subject: changed all scroll behaviors to be _scrollTop to go to a scroll and
 _scrollY to animate to it.

---
 src/client/util/DocumentManager.ts                 |  2 +-
 src/client/views/animationtimeline/Timeline.tsx    |  2 --
 src/client/views/animationtimeline/Track.tsx       |  5 +++--
 src/client/views/collections/CollectionSubView.tsx |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  2 +-
 src/client/views/nodes/PDFBox.tsx                  |  2 +-
 src/client/views/nodes/WebBox.tsx                  | 14 +++++++-------
 .../views/nodes/formattedText/FormattedTextBox.tsx |  4 ++--
 .../formattedText/FormattedTextBoxComment.tsx      |  2 +-
 src/client/views/pdf/PDFViewer.tsx                 | 22 +++++++++-------------
 src/fields/documentSchemas.ts                      |  8 ++++----
 11 files changed, 30 insertions(+), 35 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 67f2f244c..78c05f572 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -168,7 +168,7 @@ export class DocumentManager {
                 highlight();
             } else {  // otherwise try to get a view of the context of the target
                 const targetDocContextView = getFirstDocView(targetDocContext);
-                targetDocContext.scrollY = 0;  // this will force PDFs to activate and load their annotations / allow scrolling
+                targetDocContext._scrollY = 0;  // this will force PDFs to activate and load their annotations / allow scrolling
                 if (targetDocContextView) { // we found a context view and aren't forced to create a new one ... focus on the context first..
                     targetDocContext.panTransformType = "Ease";
                     targetDocContextView.props.focus(targetDocContextView.props.Document, willZoom);
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index 017623120..43f15a33f 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -11,8 +11,6 @@ import { KeyframeFunc } from "./Keyframe";
 import "./Timeline.scss";
 import { TimelineOverview } from "./TimelineOverview";
 import { Track } from "./Track";
-import { utils } from "mocha";
-import { Util } from "../../../../deploy/assets/pdf.worker";
 import clamp from "../../util/clamp";
 
 /**
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index fc96c320a..4987006e7 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -31,13 +31,14 @@ export class Track extends React.Component<IProps> {
     @observable private _autoKfReaction: any;
     @observable private _newKeyframe: boolean = false;
     private readonly MAX_TITLE_HEIGHT = 75;
-    private _trackHeight = 0;
+    @observable private _trackHeight = 0;
     private primitiveWhitelist = [
         "x",
         "y",
         "_width",
         "_height",
         "opacity",
+        "_scrollTop"
     ];
     private objectWhitelist = [
         "data"
@@ -51,7 +52,7 @@ export class Track extends React.Component<IProps> {
         if (!regions) this.props.node.regions = new List<Doc>(); //if there is no region, then create new doc to store stuff
         //these two lines are exactly same from timeline.tsx 
         const relativeHeight = window.innerHeight / 20;
-        this._trackHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT; //for responsiveness
+        runInAction(() => this._trackHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT); //for responsiveness
         this._timelineVisibleReaction = this.timelineVisibleReaction();
         this._currentBarXReaction = this.currentBarXReaction();
         if (DocListCast(this.props.node.regions).length === 0) this.createRegion(this.time);
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 423eb1d90..56c6ce457 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -343,7 +343,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
                                 if (focusNode) {
                                     const rect = "getBoundingClientRect" in focusNode ? focusNode.getBoundingClientRect() : focusNode?.parentElement.getBoundingClientRect();
                                     const x = (rect?.x || 0);
-                                    const y = NumCast(srcWeb.scrollTop) + (rect?.y || 0);
+                                    const y = NumCast(srcWeb._scrollTop) + (rect?.y || 0);
                                     const anchor = Docs.Create.FreeformDocument([], { _LODdisable: true, _backgroundColor: "transparent", _width: 25, _height: 25, x, y, annotationOn: srcWeb });
                                     anchor.context = srcWeb;
                                     const key = Doc.LayoutFieldKey(srcWeb);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index fc5e61026..80ee2a65d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -886,7 +886,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             } else {
                 const contextHgt = Doc.AreProtosEqual(annotOn, this.props.Document) && this.props.VisibleHeight ? this.props.VisibleHeight() : NumCast(annotOn._height);
                 const offset = annotOn && (contextHgt / 2 * 96 / 72);
-                this.props.Document.scrollY = NumCast(doc.y) - offset;
+                this.props.Document._scrollY = NumCast(doc.y) - offset;
             }
 
             afterFocus && setTimeout(afterFocus, 1000);
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 493f23dc4..fae216f17 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -248,7 +248,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
     _pdfjsRequested = false;
     render() {
         const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField, null);
-        if (this.props.isSelected() || this.props.renderDepth <= 1 || this.props.Document.scrollY !== undefined) this._everActive = true;
+        if (this.props.isSelected() || this.props.renderDepth <= 1 || this.props.Document._scrollY !== undefined) this._everActive = true;
         if (pdfUrl && (this._everActive || this.props.Document._scrollTop || (this.dataDoc[this.props.fieldKey + "-nativeWidth"] && this.props.ScreenToLocalTransform().Scale < 2.5))) {
             if (pdfUrl instanceof PdfField && this._pdf) {
                 return this.renderPdfView;
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index c4ab3c9e2..6aff22f41 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -58,15 +58,15 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
             iframe.contentDocument.addEventListener('pointerdown', this.iframedown, false);
             iframe.contentDocument.addEventListener('scroll', this.iframeScrolled, false);
             this.layoutDoc.scrollHeight = iframe.contentDocument.children?.[0].scrollHeight || 1000;
-            iframe.contentDocument.children[0].scrollTop = NumCast(this.layoutDoc.scrollTop);
-            iframe.contentDocument.children[0].scrollLeft = NumCast(this.layoutDoc.scrollLeft);
+            iframe.contentDocument.children[0].scrollTop = NumCast(this.layoutDoc._scrollTop);
+            iframe.contentDocument.children[0].scrollLeft = NumCast(this.layoutDoc._scrollLeft);
         }
         this._reactionDisposer?.();
-        this._reactionDisposer = reaction(() => ({ y: this.layoutDoc.scrollY, x: this.layoutDoc.scrollX }),
+        this._reactionDisposer = reaction(() => ({ y: this.layoutDoc._scrollY, x: this.layoutDoc._scrollX }),
             ({ x, y }) => {
                 if (y !== undefined) {
                     this._outerRef.current!.scrollTop = y;
-                    this.layoutDoc.scrollY = undefined;
+                    this.layoutDoc._scrollY = undefined;
                 }
                 if (x !== undefined) {
                     this._outerRef.current!.scrollLeft = x;
@@ -83,8 +83,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
     iframeScrolled = (e: any) => {
         const scrollTop = e.target?.children?.[0].scrollTop;
         const scrollLeft = e.target?.children?.[0].scrollLeft;
-        this.layoutDoc.scrollTop = this._outerRef.current!.scrollTop = scrollTop;
-        this.layoutDoc.scrollLeft = this._outerRef.current!.scrollLeft = scrollLeft;
+        this.layoutDoc._scrollTop = this._outerRef.current!.scrollTop = scrollTop;
+        this.layoutDoc._scrollLeft = this._outerRef.current!.scrollLeft = scrollLeft;
     }
     async componentDidMount() {
         const urlField = Cast(this.dataDoc[this.props.fieldKey], WebField);
@@ -440,7 +440,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
             {this.urlEditor()}
         </>);
     }
-    scrollXf = () => this.props.ScreenToLocalTransform().translate(NumCast(this.layoutDoc.scrollLeft), NumCast(this.layoutDoc.scrollTop));
+    scrollXf = () => this.props.ScreenToLocalTransform().translate(NumCast(this.layoutDoc._scrollLeft), NumCast(this.layoutDoc._scrollTop));
     render() {
         return (<div className={`webBox-container`}
             style={{
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index fc131cd38..8b98fd083 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -721,7 +721,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             },
             { fireImmediately: true }
         );
-        this._disposers.scroll = reaction(() => NumCast(this.layoutDoc.scrollPos),
+        this._disposers.scroll = reaction(() => NumCast(this.layoutDoc._scrollTop),
             pos => this._scrollRef.current && this._scrollRef.current.scrollTo({ top: pos }), { fireImmediately: true }
         );
 
@@ -1174,7 +1174,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     }
 
     onscrolled = (ev: React.UIEvent) => {
-        this.layoutDoc.scrollPos = this._scrollRef.current!.scrollTop;
+        this.layoutDoc._scrollTop = this._scrollRef.current!.scrollTop;
     }
     @action
     tryUpdateHeight(limitHeight?: number) {
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index d47ae63af..59a6045ab 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -183,7 +183,7 @@ export class FormattedTextBoxComment {
                             const anchor = FieldValue(Doc.AreProtosEqual(FieldValue(Cast(linkDoc.anchor1, Doc)), textBox.dataDoc) ? Cast(linkDoc.anchor2, Doc) : (Cast(linkDoc.anchor1, Doc)) || linkDoc);
                             const target = anchor?.annotationOn ? await DocCastAsync(anchor.annotationOn) : anchor;
                             if (anchor !== target && anchor && target) {
-                                target.scrollY = NumCast(anchor?.y);
+                                target._scrollY = NumCast(anchor?.y);
                             }
                             if (target) {
                                 ReactDOM.render(<ContentFittingDocumentView
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 5bad248be..ec5c3f4ff 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -2,7 +2,6 @@ import { action, computed, IReactionDisposer, observable, reaction, runInAction
 import { observer } from "mobx-react";
 import * as Pdfjs from "pdfjs-dist";
 import "pdfjs-dist/web/pdf_viewer.css";
-import * as rp from "request-promise";
 import { Dictionary } from "typescript-collections";
 import { Doc, DocListCast, FieldResult, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
 import { documentSchema } from "../../../fields/documentSchemas";
@@ -38,9 +37,7 @@ import { Networking } from "../../Network";
 
 export const pageSchema = createSchema({
     curPage: "number",
-    fitWidth: "boolean",
     rotation: "number",
-    scrollY: "number",
     scrollHeight: "number",
     serachMatch: "boolean"
 });
@@ -95,7 +92,6 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
     @observable private _showWaiting = true;
     @observable private _showCover = false;
     @observable private _zoomed = 1;
-    @observable private _scrollTop = 0;
 
     private _pdfViewer: any;
     private _retries = 0; // number of times tried to create the PDF viewer 
@@ -143,6 +139,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
         this._coverPath = href.startsWith(window.location.origin) ? await Networking.PostToServer("/thumbnail", params) : { width: 100, height: 100, path: "" };
         runInAction(() => this._showWaiting = this._showCover = true);
         this.props.startupLive && this.setupPdfJsViewer();
+        this._mainCont.current!.scrollTop = this.layoutDoc._scrollTop || 0;
         this._searchReactionDisposer = reaction(() => this.Document.searchMatch, search => {
             if (search) {
                 this.search(Doc.SearchQuery(), true);
@@ -158,14 +155,12 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
             () => (SelectionManager.SelectedDocuments().length === 1) && this.setupPdfJsViewer(),
             { fireImmediately: true });
         this._reactionDisposer = reaction(
-            () => this.Document.scrollY,
+            () => this.Document._scrollY,
             (scrollY) => {
                 if (scrollY !== undefined) {
-                    if (this._showCover || this._showWaiting) {
-                        this.setupPdfJsViewer();
-                    }
-                    this._mainCont.current && smoothScroll(1000, this._mainCont.current, (this.Document.scrollY || 0));
-                    this.Document.scrollY = undefined;
+                    (this._showCover || this._showWaiting) && this.setupPdfJsViewer();
+                    this._mainCont.current && smoothScroll(1000, this._mainCont.current, (this.Document._scrollY || 0));
+                    setTimeout(() => this.Document._scrollY = undefined, 1000);
                 }
             },
             { fireImmediately: true }
@@ -220,7 +215,8 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
         await this.initialLoad();
 
         this._scrollTopReactionDisposer = reaction(() => Cast(this.layoutDoc._scrollTop, "number", null),
-            (stop) => (stop !== undefined) && this._mainCont.current && smoothScroll(500, this._mainCont.current, stop), { fireImmediately: true });
+            (stop) => (stop !== undefined && this.layoutDoc._scrollY === undefined) && (this._mainCont.current!.scrollTop = stop), { fireImmediately: true });
+
         this._annotationReactionDisposer = reaction(
             () => DocListCast(this.dataDoc[this.props.fieldKey + "-annotations"]),
             annotations => annotations?.length && (this._annotations = annotations),
@@ -352,7 +348,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
 
     @action
     onScroll = (e: React.UIEvent<HTMLElement>) => {
-        this._scrollTop = this._mainCont.current!.scrollTop;
+        this.Document._scrollY === undefined && (this.layoutDoc._scrollTop = this._mainCont.current!.scrollTop);
         this._pdfViewer && (this.Document.curPage = this._pdfViewer.currentPageNumber);
     }
 
@@ -604,7 +600,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
     }
 
     scrollXf = () => {
-        return this._mainCont.current ? this.props.ScreenToLocalTransform().translate(0, this._scrollTop) : this.props.ScreenToLocalTransform();
+        return this._mainCont.current ? this.props.ScreenToLocalTransform().translate(0, this.layoutDoc._scrollTop || 0) : this.props.ScreenToLocalTransform();
     }
     onClick = (e: React.MouseEvent) => {
         this._setPreviewCursor &&
diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts
index e7031cc39..e0a02d93c 100644
--- a/src/fields/documentSchemas.ts
+++ b/src/fields/documentSchemas.ts
@@ -22,10 +22,10 @@ export const documentSchema = createSchema({
     y: "number",                // y coordinate when in a freeform view 
     z: "number",                // z "coordinate" - non-zero specifies the overlay layer of a freeformview
     zIndex: "number",           // zIndex of a document in a freeform view
-    scrollY: "number",          // "command" to scroll a document to a position on load (the value will be reset to 0 after that )
-    scrollX: "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)
-    scrollLeft: "number",        // scroll position of a scrollable document (pdf, text, web)
+    _scrollY: "number",          // "command" to scroll a document to a position on load (the value will be reset to 0 after that )
+    _scrollX: "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)
+    _scrollLeft: "number",        // scroll position of a scrollable document (pdf, text, web)
 
     // appearance properties on the layout
     _autoHeight: "boolean",     // whether the height of the document should be computed automatically based on its contents
-- 
cgit v1.2.3-70-g09d2

