From 464bca333ba97185dcbc93409001adeb26711902 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 1 Jul 2021 22:43:47 -0400
Subject: added ability to create anchors in PDF/Webboxes by making a selection
 and clicking the start link button

---
 src/client/views/nodes/PDFBox.tsx | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

(limited to 'src/client/views/nodes/PDFBox.tsx')

diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index feaeb9e21..8f61e252b 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -23,6 +23,7 @@ import { FieldView, FieldViewProps } from './FieldView';
 import { pageSchema } from "./ImageBox";
 import "./PDFBox.scss";
 import React = require("react");
+import { AnchorMenu } from '../pdf/AnchorMenu';
 
 type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>;
 const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema);
@@ -94,11 +95,13 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         return this._pdfViewer?.scrollFocus(doc, smooth);
     }
     getAnchor = () => {
-        const anchor = Docs.Create.TextanchorDocument({
-            title: StrCast(this.rootDoc.title + " " + this.layoutDoc._scrollTop),
-            annotationOn: this.rootDoc,
-            y: NumCast(this.layoutDoc._scrollTop),
-        });
+        const anchor =
+            AnchorMenu.Instance?.GetAnchor() ??
+            Docs.Create.TextanchorDocument({
+                title: StrCast(this.rootDoc.title + " " + this.layoutDoc._scrollTop),
+                annotationOn: this.rootDoc,
+                y: NumCast(this.layoutDoc._scrollTop),
+            });
         this.addDocument(anchor);
         return anchor;
     }
-- 
cgit v1.2.3-70-g09d2


From 0546ecf205b7d2b76f341a7157beebf95fb888a8 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sun, 1 Aug 2021 22:43:46 -0400
Subject: made url server references relative.

---
 src/Utils.ts                                       |  1 -
 .../apis/google_docs/GooglePhotosClientUtils.ts    |  2 +-
 src/client/documents/Documents.ts                  | 90 ++--------------------
 src/client/util/HypothesisUtils.ts                 |  2 +-
 src/client/views/collections/CollectionSubView.tsx |  2 +-
 .../views/collections/CollectionTimeView.tsx       |  2 +-
 src/client/views/nodes/AudioBox.tsx                |  2 +-
 src/client/views/nodes/DocumentLinksButton.tsx     |  2 +-
 src/client/views/nodes/DocumentView.tsx            |  6 +-
 src/client/views/nodes/FieldView.tsx               |  6 +-
 src/client/views/nodes/ImageBox.tsx                |  2 +-
 src/client/views/nodes/LinkDocPreview.tsx          |  4 +-
 src/client/views/nodes/PDFBox.tsx                  | 24 ------
 src/client/views/nodes/ScreenshotBox.tsx           |  4 +-
 src/client/views/nodes/VideoBox.tsx                |  8 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |  6 +-
 .../views/nodes/formattedText/RichTextMenu.tsx     |  8 +-
 src/client/views/pdf/AnchorMenu.tsx                |  1 -
 src/fields/Doc.ts                                  | 12 ++-
 src/fields/URLField.ts                             | 15 +++-
 src/mobile/ImageUpload.tsx                         |  2 +-
 src/server/server_Initialization.ts                |  3 +-
 22 files changed, 58 insertions(+), 146 deletions(-)

(limited to 'src/client/views/nodes/PDFBox.tsx')

diff --git a/src/Utils.ts b/src/Utils.ts
index d87c3cc6b..194c38a6f 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -67,7 +67,6 @@ export namespace Utils {
     export function prepend(extension: string): string {
         return window.location.origin + extension;
     }
-
     export function fileUrl(filename: string): string {
         return prepend(`/files/${filename}`);
     }
diff --git a/src/client/apis/google_docs/GooglePhotosClientUtils.ts b/src/client/apis/google_docs/GooglePhotosClientUtils.ts
index 899e65a16..ff9460b62 100644
--- a/src/client/apis/google_docs/GooglePhotosClientUtils.ts
+++ b/src/client/apis/google_docs/GooglePhotosClientUtils.ts
@@ -285,7 +285,7 @@ export namespace GooglePhotos {
             const photos = await endpoint();
             const albumId = StrCast(collection.albumId);
             if (albumId && albumId.length) {
-                const enrichment = new photos.TextEnrichment(content || Utils.prepend("/doc/" + collection[Id]));
+                const enrichment = new photos.TextEnrichment(content || Doc.globalServerPath(collection));
                 const position = new photos.AlbumPosition(photos.AlbumPosition.POSITIONS.FIRST_IN_ALBUM);
                 const enrichmentItem = await photos.albums.addEnrichment(albumId, enrichment, position);
                 if (enrichmentItem) {
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index e863b4198..ac52b0acf 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -549,84 +549,6 @@ export namespace Docs {
      */
     export namespace Create {
 
-        /**
-         * Synchronously returns a collection into which
-         * the device documents will be put. This is initially empty,
-         * but gets populated by updates from the web socket. When everything is over,
-         * this function cleans up after itself.
-         * s
-         * Look at Websocket.ts for the server-side counterpart to this
-         * function.
-         */
-        export function Buxton() {
-            let responded = false;
-            const loading = new Doc;
-            loading.title = "Please wait for the import script...";
-            const parent = TreeDocument([loading], {
-                title: "The Buxton Collection",
-                _width: 400,
-                _height: 400
-            });
-            const parentProto = Doc.GetProto(parent);
-            const { _socket } = DocServer;
-
-            // just in case, clean up
-            _socket.off(MessageStore.BuxtonDocumentResult.Message);
-            _socket.off(MessageStore.BuxtonImportComplete.Message);
-
-            // this is where the client handles the receipt of a new valid parsed document
-            Utils.AddServerHandler(_socket, MessageStore.BuxtonDocumentResult, ({ device, invalid: errors }) => {
-                if (!responded) {
-                    responded = true;
-                    parentProto.data = new List<Doc>();
-                }
-                if (device) {
-                    const { title, __images, additionalMedia } = device;
-                    delete device.__images;
-                    delete device.additionalMedia;
-                    const { ImageDocument, StackingDocument } = Docs.Create;
-                    const constructed = __images.map(({ url, nativeWidth, nativeHeight }) => ({ url: Utils.prepend(url), nativeWidth, nativeHeight }));
-                    const deviceImages = constructed.map(({ url, nativeWidth, nativeHeight }, i) => {
-                        const imageDoc = ImageDocument(url, {
-                            title: `image${i}.${extname(url)}`,
-                            _nativeWidth: nativeWidth,
-                            _nativeHeight: nativeHeight
-                        });
-                        const media = additionalMedia[i];
-                        if (media) {
-                            for (const key of Object.keys(media)) {
-                                imageDoc[`additionalMedia_${key}`] = Utils.prepend(`/files/${key}/buxton/${media[key]}`);
-                            }
-                        }
-                        return imageDoc;
-                    });
-                    // the main document we create
-                    const doc = StackingDocument(deviceImages, { title, hero: new ImageField(constructed[0].url) });
-                    doc.nameAliases = new List<string>([title.toLowerCase()]);
-                    // add the parsed attributes to this main document
-                    Doc.Get.FromJson({ data: device, appendToExisting: { targetDoc: Doc.GetProto(doc) } });
-                    Doc.AddDocToList(parentProto, "data", doc);
-                } else if (errors) {
-                    console.log("Documents:" + errors);
-                } else {
-                    alert("A Buxton document import was completely empty (??)");
-                }
-            });
-
-            // when the import is complete, we stop listening for these creation
-            // and termination events and alert the user
-            Utils.AddServerHandler(_socket, MessageStore.BuxtonImportComplete, ({ deviceCount, errorCount }) => {
-                _socket.off(MessageStore.BuxtonDocumentResult.Message);
-                _socket.off(MessageStore.BuxtonImportComplete.Message);
-                alert(`Successfully imported ${deviceCount} device${deviceCount === 1 ? "" : "s"}, with ${errorCount} error${errorCount === 1 ? "" : "s"}, in ${(Date.now() - startTime) / 1000} seconds.`);
-            });
-            const startTime = Date.now();
-            Utils.Emit(_socket, MessageStore.BeginBuxtonImport, ""); // signal the server to start importing
-            return parent; // synchronously return the collection, to be populateds
-        }
-
-        Scripting.addGlobal(Buxton);
-
         /**
          * This function receives the relevant document prototype and uses
          * it to create a new of that base-level prototype, or the
@@ -675,7 +597,7 @@ export namespace Docs {
         }
 
         export function ImageDocument(url: string, options: DocumentOptions = {}) {
-            const imgField = new ImageField(new URL(url));
+            const imgField = new ImageField(url);
             return InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: path.basename(url), ...options });
         }
 
@@ -689,11 +611,11 @@ export namespace Docs {
         }
 
         export function VideoDocument(url: string, options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.VID), new VideoField(new URL(url)), options);
+            return InstanceFromProto(Prototypes.get(DocumentType.VID), new VideoField(url), options);
         }
 
         export function YoutubeDocument(url: string, options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.YOUTUBE), new YoutubeField(new URL(url)), options);
+            return InstanceFromProto(Prototypes.get(DocumentType.YOUTUBE), new YoutubeField(url), options);
         }
 
         export function WebCamDocument(url: string, options: DocumentOptions = {}) {
@@ -709,7 +631,7 @@ export namespace Docs {
         }
 
         export function AudioDocument(url: string, options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.AUDIO), new AudioField(new URL(url)),
+            return InstanceFromProto(Prototypes.get(DocumentType.AUDIO), new AudioField(url),
                 { ...options, backgroundColor: ComputedField.MakeFunction("this._mediaState === 'playing' ? 'green':'gray'") as any });
         }
 
@@ -782,11 +704,11 @@ export namespace Docs {
         }
 
         export function PdfDocument(url: string, options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.PDF), new PdfField(new URL(url)), options);
+            return InstanceFromProto(Prototypes.get(DocumentType.PDF), new PdfField(url), options);
         }
 
         export function WebDocument(url: string, options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.WEB), url ? new WebField(new URL(url)) : undefined, options);
+            return InstanceFromProto(Prototypes.get(DocumentType.WEB), url ? new WebField(url) : undefined, options);
         }
 
         export function HtmlDocument(html: string, options: DocumentOptions = {}) {
diff --git a/src/client/util/HypothesisUtils.ts b/src/client/util/HypothesisUtils.ts
index 8ddfce772..635673025 100644
--- a/src/client/util/HypothesisUtils.ts
+++ b/src/client/util/HypothesisUtils.ts
@@ -126,7 +126,7 @@ export namespace Hypothesis {
         });
 
         const annotationId = StrCast(linkDoc.annotationId);
-        const linkUrl = Utils.prepend("/doc/" + sourceDoc[Id]);
+        const linkUrl = Doc.globalServerPath(sourceDoc);
         const interval = setInterval(() => {// keep trying to edit until annotations have loaded and editing is successful
             !success && document.dispatchEvent(new CustomEvent<{ targetUrl: string, id: string }>("deleteLink", {
                 detail: { targetUrl: linkUrl, id: annotationId },
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index a5d27f038..0d9b64d24 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -303,7 +303,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
                     } else {
                         const path = window.location.origin + "/doc/";
                         if (text.startsWith(path)) {
-                            const docid = text.replace(Utils.prepend("/doc/"), "").split("?")[0];
+                            const docid = text.replace(Doc.globalServerPath(), "").split("?")[0];
                             DocServer.GetRefField(docid).then(f => {
                                 if (f instanceof Doc) {
                                     if (options.x || options.y) { f.x = options.x; f.y = options.y; } // should be in CollectionFreeFormView
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index 339163510..08b5e6bac 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -37,7 +37,7 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) {
     @observable _focusRangeFilters: Opt<string[]>;
 
     getAnchor = () => {
-        const anchor = Docs.Create.HTMLAnchorDocument({
+        const anchor = Docs.Create.HTMLAnchorDocument([], {
             title: ComputedField.MakeFunction(`"${this.pivotField}"])`) as any,
             annotationOn: this.rootDoc
         });
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index a2e36f12e..82bad971d 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -196,7 +196,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         this._recorder.ondataavailable = async (e: any) => {
             const [{ result }] = await Networking.UploadFilesToServer(e.data);
             if (!(result instanceof Error)) {
-                this.props.Document[this.props.fieldKey] = new AudioField(Utils.prepend(result.accessPaths.agnostic.client));
+                this.props.Document[this.props.fieldKey] = new AudioField(result.accessPaths.agnostic.client);
             }
         };
         this._recordStart = new Date().getTime();
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index ddc36daa1..aa3f10188 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -194,7 +194,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                 Doc.GetProto(linkDoc as Doc).linksToAnnotation = true;
                 Doc.GetProto(linkDoc as Doc).annotationId = DocumentLinksButton.AnnotationId;
                 Doc.GetProto(linkDoc as Doc).annotationUri = DocumentLinksButton.AnnotationUri;
-                const dashHyperlink = Utils.prepend("/doc/" + (startIsAnnotation ? endLink[Id] : startLink[Id]));
+                const dashHyperlink = Doc.globalServerPath(startIsAnnotation ? endLink : startLink);
                 Hypothesis.makeLink(StrCast(startIsAnnotation ? endLink.title : startLink.title), dashHyperlink, DocumentLinksButton.AnnotationId,
                     (startIsAnnotation ? startLink : endLink)); // edit annotation to add a Dash hyperlink to the linked doc
             }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 60fa462ad..b8ccc4712 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -746,7 +746,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                         moreItems.push({ description: "Tag Child Images via Google Photos", event: () => GooglePhotos.Query.TagChildImages(this.props.Document), icon: "caret-square-right" });
                         moreItems.push({ description: "Write Back Link to Album", event: () => GooglePhotos.Transactions.AddTextEnrichment(this.props.Document), icon: "caret-square-right" });
                     }
-                    moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" });
+                    moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Doc.globalServerPath(this.props.Document)), icon: "fingerprint" });
                 }
             }
 
@@ -760,7 +760,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             const help = cm.findByDescription("Help...");
             const helpItems: ContextMenuProps[] = help && "subitems" in help ? help.subitems : [];
             !Doc.UserDoc().novice && helpItems.push({ description: "Show Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "add:right"), icon: "layer-group" });
-            helpItems.push({ description: "Text Shortcuts Ctrl+/", event: () => this.props.addDocTab(Docs.Create.PdfDocument(Utils.prepend("/assets/cheat-sheet.pdf"), { _width: 300, _height: 300 }), "add:right"), icon: "keyboard" });
+            helpItems.push({ description: "Text Shortcuts Ctrl+/", event: () => this.props.addDocTab(Docs.Create.PdfDocument("/assets/cheat-sheet.pdf", { _width: 300, _height: 300 }), "add:right"), icon: "keyboard" });
             !Doc.UserDoc().novice && helpItems.push({ description: "Print Document in Console", event: () => console.log(this.props.Document), icon: "hand-point-right" });
             cm.addItem({ description: "Help...", noexpand: true, subitems: helpItems, icon: "question" });
         }
@@ -885,7 +885,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             recorder.ondataavailable = async (e: any) => {
                 const [{ result }] = await Networking.UploadFilesToServer(e.data);
                 if (!(result instanceof Error)) {
-                    const audioDoc = Docs.Create.AudioDocument(Utils.prepend(result.accessPaths.agnostic.client), { title: "audio test", _width: 200, _height: 32 });
+                    const audioDoc = Docs.Create.AudioDocument(result.accessPaths.agnostic.client, { title: "audio test", _width: 200, _height: 32 });
                     audioDoc.treeViewExpandedView = "layout";
                     const audioAnnos = Cast(self.dataDoc[self.LayoutFieldKey + "-audioAnnotations"], listSpec(Doc));
                     if (audioAnnos === undefined) {
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 86250c9d1..ebbc1138a 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -64,9 +64,9 @@ export class FieldView extends React.Component<FieldViewProps> {
         // else if (field instaceof PresBox) {
         //    return <PresBox {...this.props} />;
         // }
-        else if (field instanceof VideoField) {
-            return <VideoBox {...this.props} />;
-        }
+        // else if (field instanceof VideoField) {
+        //     return <VideoBox {...this.props} />;
+        // }
         // else if (field instanceof AudioField) {
         //     return <AudioBox {...this.props} />;
         //}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index cfd43bb62..2c0106960 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -238,7 +238,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
                     let succeeded = true;
                     let data: ImageField | undefined;
                     try {
-                        data = new ImageField(Utils.prepend(accessPaths.agnostic.client));
+                        data = new ImageField(accessPaths.agnostic.client);
                     } catch {
                         succeeded = false;
                     }
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index b73fb10df..126a37eb8 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -72,14 +72,14 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
     @computed get href() {
         if (this.props.hrefs?.length) {
             const href = this.props.hrefs[this._hrefInd];
-            if (href.indexOf(Utils.prepend("/doc/")) !== 0) {  // link to a web page URL -- try to show a preview
+            if (href.indexOf(Doc.localServerPath()) !== 0) {  // link to a web page URL -- try to show a preview
                 if (href.startsWith("https://en.wikipedia.org/wiki/")) {
                     wiki().page(href.replace("https://en.wikipedia.org/wiki/", "")).then(page => page.summary().then(action(summary => this._toolTipText = summary.substring(0, 500))));
                 } else {
                     setTimeout(action(() => this._toolTipText = "url => " + href));
                 }
             } else { // hyperlink to a document .. decode doc id and retrieve from the server. this will trigger vals() being invalidated
-                const anchorDoc = href.replace(Utils.prepend("/doc/"), "").split("?")[0];
+                const anchorDoc = href.replace(Doc.localServerPath(), "").split("?")[0];
                 anchorDoc && DocServer.GetRefField(anchorDoc).then(action(anchor => {
                     if (anchor instanceof Doc && DocListCast(anchor.links).length) {
                         this._linkDoc = DocListCast(anchor.links)[0];
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 8f61e252b..0b451e2b4 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -53,30 +53,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             if (PDFBox.pdfcache.get(this.pdfUrl.url.href)) runInAction(() => this._pdf = PDFBox.pdfcache.get(this.pdfUrl!.url.href));
             else if (PDFBox.pdfpromise.get(this.pdfUrl.url.href)) PDFBox.pdfpromise.get(this.pdfUrl.url.href)?.then(action(pdf => this._pdf = pdf));
         }
-
-        const backup = "oldPath";
-        const href = this.pdfUrl?.url.href;
-        if (href) {
-            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(this.props.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?.(); }
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index 700f8a7d3..0e235a62d 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -227,7 +227,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
             this._audioRec.onstop = async (e: any) => {
                 const [{ result }] = await Networking.UploadFilesToServer(aud_chunks);
                 if (!(result instanceof Error)) {
-                    this.dataDoc[this.props.fieldKey + "-audio"] = new AudioField(Utils.prepend(result.accessPaths.agnostic.client));
+                    this.dataDoc[this.props.fieldKey + "-audio"] = new AudioField(result.accessPaths.agnostic.client);
                 }
             };
             this._videoRef!.srcObject = await (navigator.mediaDevices as any).getDisplayMedia({ video: true });
@@ -244,7 +244,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
                     this.layoutDoc.layout = VideoBox.LayoutString(this.fieldKey);
                     this.dataDoc.nativeWidth = this.dataDoc.nativeHeight = undefined;
                     this.layoutDoc._fitWidth = undefined;
-                    this.dataDoc[this.props.fieldKey] = new VideoField(Utils.prepend(result.accessPaths.agnostic.client));
+                    this.dataDoc[this.props.fieldKey] = new VideoField(result.accessPaths.agnostic.client);
                 } else alert("video conversion failed");
             };
             this._audioRec.start();
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index fc08a2302..ce45c01e6 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -75,10 +75,6 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         return CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey, "_timecodeToShow"/* videoStart */, "_timecodeToHide" /* videoEnd */, timecode ? timecode : undefined) || this.rootDoc;
     }
 
-    choosePath(url: string) {
-        return url.indexOf(window.location.origin) === -1 ? Utils.CorsProxy(url) : url;
-    }
-
     videoLoad = () => {
         const aspect = this.player!.videoWidth / this.player!.videoHeight;
         Doc.SetNativeWidth(this.dataDoc, this.player!.videoWidth);
@@ -182,8 +178,8 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         }
     }
 
-    private createRealSummaryLink = (relative: string, downX?: number, downY?: number) => {
-        const url = this.choosePath(Utils.prepend(relative));
+    private createRealSummaryLink = (imagePath: string, downX?: number, downY?: number) => {
+        const url = !imagePath.startsWith("/") ? Utils.CorsProxy(imagePath) : imagePath;
         const width = this.layoutDoc._width || 1;
         const height = this.layoutDoc._height || 0;
         const imageSummary = Docs.Create.ImageDocument(url, {
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 140d39929..f7e9ee028 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -371,7 +371,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                 this._searchIndex = ++this._searchIndex > flattened.length - 1 ? 0 : this._searchIndex;
                 const anchor = Docs.Create.TextanchorDocument();
                 const alink = DocUtils.MakeLink({ doc: anchor }, { doc: target }, "automatic")!;
-                const allAnchors = [{ href: Utils.prepend("/doc/" + anchor[Id]), title: "a link", anchorId: anchor[Id] }];
+                const allAnchors = [{ href: Doc.localServerPath(anchor), title: "a link", anchorId: anchor[Id] }];
                 const link = this._editorView!.state.schema.marks.linkAnchor.create({ allAnchors, title: "auto link", location });
                 tr = tr.addMark(flattened[i].from, flattened[i].to, link);
             });
@@ -705,7 +705,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             let tr = state.tr.addMark(sel.from, sel.to, splitter);
             if (sel.from !== sel.to) {
                 const anchor = anchorDoc ?? Docs.Create.TextanchorDocument({ title: this._editorView?.state.doc.textBetween(sel.from, sel.to) });
-                const href = targetHref ?? Utils.prepend("/doc/" + anchor[Id]);
+                const href = targetHref ?? Doc.localServerPath(anchor);
                 if (anchor !== anchorDoc) this.addDocument(anchor);
                 tr.doc.nodesBetween(sel.from, sel.to, (node: any, pos: number, parent: any) => {
                     if (node.firstChild === null && node.marks.find((m: Mark) => m.type.name === schema.marks.splitter.name)) {
@@ -1042,7 +1042,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             }
             const marks = [...node.marks];
             const linkIndex = marks.findIndex(mark => mark.type.name === "link");
-            const allLinks = [{ href: Utils.prepend(`/doc/${linkId}`), title, linkId }];
+            const allLinks = [{ href: Doc.globalServerPath(linkId), title, linkId }];
             const link = view.state.schema.mark(view.state.schema.marks.linkAnchor, { allLinks, location: "add:right", title, docref: true });
             marks.splice(linkIndex === -1 ? 0 : linkIndex, 1, link);
             return node.mark(marks);
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index a6f8ff2e2..fb4114023 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -821,8 +821,8 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps>   {
         if (link) {
             const href = link.attrs.allAnchors.length > 0 ? link.attrs.allAnchors[0].href : undefined;
             if (href) {
-                if (href.indexOf(Utils.prepend("/doc/")) === 0) {
-                    const linkclicked = href.replace(Utils.prepend("/doc/"), "").split("?")[0];
+                if (href.indexOf(Doc.localServerPath()) === 0) {
+                    const linkclicked = href.replace(Doc.localServerPath(), "").split("?")[0];
                     if (linkclicked) {
                         const linkDoc = await DocServer.GetRefField(linkclicked);
                         if (linkDoc instanceof Doc) {
@@ -864,8 +864,8 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps>   {
                 const allAnchors = linkAnchor.attrs.allAnchors.slice();
                 this.TextView.RemoveAnchorFromSelection(allAnchors);
                 // bcz: Argh ... this will remove the link from the document even it's anchored somewhere else in the text which happens if only part of the anchor text was selected.
-                allAnchors.filter((aref: any) => aref?.href.indexOf(Utils.prepend("/doc/")) === 0).forEach((aref: any) => {
-                    const anchorId = aref.href.replace(Utils.prepend("/doc/"), "").split("?")[0];
+                allAnchors.filter((aref: any) => aref?.href.indexOf(Doc.localServerPath()) === 0).forEach((aref: any) => {
+                    const anchorId = aref.href.replace(Doc.localServerPath(), "").split("?")[0];
                     anchorId && DocServer.GetRefField(anchorId).then(linkDoc => LinkManager.Instance.deleteLink(linkDoc as Doc));
                 });
             }
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index 70ca19842..55816ed52 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -85,7 +85,6 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
     @action
     toggleLinkPopup = (e: React.MouseEvent) => {
         //ignore the potential null type error because this method cannot be called unless the user selects text and clicks the link button
-        console.log(window.getSelection().toString())
         //change popup visibility field to visible
         this._showLinkPopup = !this._showLinkPopup;
     }
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 111fd3f0d..a7e5d8541 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -596,7 +596,7 @@ export namespace Doc {
                 const mapped = cloneMap.get(id);
                 return href + (mapped ? mapped[Id] : id);
             };
-            const regex = `(${Utils.prepend("/doc/")})([^"]*)`;
+            const regex = `(${Doc.localServerPath()})([^"]*)`;
             const re = new RegExp(regex, "g");
             copy[key] = new RichTextField(field.Data.replace(/("textId":|"audioId":|"anchorId":)"([^"]+)"/g, replacer).replace(re, replacer2), field.Text);
         });
@@ -896,6 +896,16 @@ export namespace Doc {
         return true;
     }
 
+
+    // converts a document id to a url path on the server
+    export function globalServerPath(doc: Doc | string = ""): string {
+        return Utils.prepend("/doc/" + (doc instanceof Doc ? doc[Id] : doc));
+    }
+    // converts a document id to a url path on the server
+    export function localServerPath(doc?: Doc): string {
+        return "/doc/" + (doc ? doc[Id] : "");
+    }
+
     export function overlapping(doc1: Doc, doc2: Doc, clusterDistance: number) {
         const doc2Layout = Doc.Layout(doc2);
         const doc1Layout = Doc.Layout(doc1);
diff --git a/src/fields/URLField.ts b/src/fields/URLField.ts
index fb71160ca..d96e8a70a 100644
--- a/src/fields/URLField.ts
+++ b/src/fields/URLField.ts
@@ -3,14 +3,17 @@ import { serializable, custom } from "serializr";
 import { ObjectField } from "./ObjectField";
 import { ToScriptString, ToString, Copy } from "./FieldSymbols";
 import { Scripting, scriptingGlobal } from "../client/util/Scripting";
+import { Utils } from "../Utils";
 
 function url() {
     return custom(
         function (value: URL) {
-            return value.href;
+            return value.origin === window.location.origin ?
+                value.pathname :
+                value.href;
         },
         function (jsonValue: string) {
-            return new URL(jsonValue);
+            return new URL(jsonValue, window.location.origin);
         }
     );
 }
@@ -24,15 +27,21 @@ export abstract class URLField extends ObjectField {
     constructor(url: URL | string) {
         super();
         if (typeof url === "string") {
-            url = new URL(url);
+            url = url.startsWith("http") ? new URL(url) : new URL(url, window.location.origin);
         }
         this.url = url;
     }
 
     [ToScriptString]() {
+        if (Utils.prepend(this.url.pathname) === this.url.href) {
+            return `new ${this.constructor.name}("${this.url.pathname}")`;
+        }
         return `new ${this.constructor.name}("${this.url.href}")`;
     }
     [ToString]() {
+        if (Utils.prepend(this.url.pathname) === this.url.href) {
+            return this.url.pathname;
+        }
         return this.url.href;
     }
 
diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx
index 98696496f..f910d765e 100644
--- a/src/mobile/ImageUpload.tsx
+++ b/src/mobile/ImageUpload.tsx
@@ -50,7 +50,7 @@ export class Uploader extends React.Component<ImageUploadProps> {
                             if (result instanceof Error) {
                                 return;
                             }
-                            const path = Utils.prepend(result.accessPaths.agnostic.client);
+                            const path = result.accessPaths.agnostic.client;
                             let doc = null;
                             // Case 1: File is a video
                             if (file.type === "video/mp4") {
diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts
index e40f2b8e5..0f4a067fc 100644
--- a/src/server/server_Initialization.ts
+++ b/src/server/server_Initialization.ts
@@ -142,8 +142,9 @@ function registerCorsProxy(server: express.Express) {
     const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
     server.use("/corsProxy", async (req, res) => {
 
-        const requrl = decodeURIComponent(req.url.substring(1));
         const referer = req.headers.referer ? decodeURIComponent(req.headers.referer) : "";
+        const requrlraw = decodeURIComponent(req.url.substring(1));
+        const requrl = requrlraw.startsWith("/") ? referer + requrlraw : requrlraw;
         // cors weirdness here... 
         // if the referer is a cors page and the cors() route (I think) redirected to /corsProxy/<path> and the requested url path was relative, 
         // then we redirect again to the cors referer and just add the relative path.
-- 
cgit v1.2.3-70-g09d2


From 6d9c65bf95091b0d5ee7e3097995fc9e2ead4415 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 5 Aug 2021 11:21:04 -0400
Subject: improved opening sidebar when following a link to a sidebar
 annotation.  Still needs work when link is from outside of the sidebar
 document and on first click.

---
 src/client/views/SidebarAnnos.tsx                  |  5 +++--
 src/client/views/nodes/PDFBox.tsx                  | 26 +++++++++++++++-------
 src/client/views/nodes/WebBox.tsx                  | 24 ++++++++++++++------
 .../views/nodes/formattedText/FormattedTextBox.tsx | 21 ++++++++++++-----
 4 files changed, 53 insertions(+), 23 deletions(-)

(limited to 'src/client/views/nodes/PDFBox.tsx')

diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx
index 7b11723c3..f1d168a22 100644
--- a/src/client/views/SidebarAnnos.tsx
+++ b/src/client/views/SidebarAnnos.tsx
@@ -23,6 +23,7 @@ interface ExtraProps {
     layoutDoc: Doc;
     rootDoc: Doc;
     dataDoc: Doc;
+    showSidebar: boolean;
     whenChildContentsActiveChanged: (isActive: boolean) => void;
     ScreenToLocalTransform: () => Transform;
     sidebarAddDocument: (doc: (Doc | Doc[]), suffix: string) => boolean;
@@ -75,7 +76,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
     get sidebarKey() { return this.props.fieldKey + "-sidebar"; }
     filtersHeight = () => 38;
     screenToLocalTransform = () => this.props.ScreenToLocalTransform().translate(Doc.NativeWidth(this.props.dataDoc), 0).scale(this.props.scaling?.() || 1);
-    panelWidth = () => !this.props.layoutDoc._showSidebar ? 0 : this.props.layoutDoc.type === DocumentType.RTF ? this.props.PanelWidth() : (NumCast(this.props.layoutDoc.nativeWidth) - Doc.NativeWidth(this.props.dataDoc)) * this.props.PanelWidth() / NumCast(this.props.layoutDoc.nativeWidth);
+    panelWidth = () => !this.props.showSidebar ? 0 : this.props.layoutDoc.type === DocumentType.RTF ? this.props.PanelWidth() : (NumCast(this.props.layoutDoc.nativeWidth) - Doc.NativeWidth(this.props.dataDoc)) * this.props.PanelWidth() / NumCast(this.props.layoutDoc.nativeWidth);
     panelHeight = () => this.props.PanelHeight() - this.filtersHeight();
     addDocument = (doc: Doc | Doc[]) => this.props.sidebarAddDocument(doc, this.sidebarKey);
     moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument(doc, targetCollection, addDocument, this.sidebarKey);
@@ -103,7 +104,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
                 {user}
             </div>;
         };
-        return !this.props.layoutDoc._showSidebar ? (null) :
+        return !this.props.showSidebar ? (null) :
             <div style={{
                 position: "absolute", pointerEvents: this.props.isContentActive() ? "all" : undefined, top: 0, right: 0,
                 background: this.props.styleProvider?.(this.props.rootDoc, this.props, StyleProp.WidgetColor),
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 0b451e2b4..fc8fa4eef 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -3,10 +3,10 @@ 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 { Doc, Opt, WidthSym } from "../../../fields/Doc";
+import { Doc, Opt, WidthSym, DocListCast } from "../../../fields/Doc";
 import { documentSchema } from '../../../fields/documentSchemas';
 import { makeInterface } from "../../../fields/Schema";
-import { Cast, NumCast, StrCast } from '../../../fields/Types';
+import { Cast, NumCast, StrCast, BoolCast } from '../../../fields/Types';
 import { PdfField } from "../../../fields/URLField";
 import { TraceMobx } from '../../../fields/util';
 import { Utils, setupMoveUpEvents, emptyFunction } from '../../../Utils';
@@ -66,6 +66,9 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     }
 
     scrollFocus = (doc: Doc, smooth: boolean) => {
+        if (DocListCast(this.props.Document[this.fieldKey + "-sidebar"]).includes(doc) && !this.SidebarShown) {
+            this.toggleSidebar(!smooth);
+        }
         if (this._sidebarRef?.current?.makeDocUnfiltered(doc)) return 1;
         this._initialScrollTarget = doc;
         return this._pdfViewer?.scrollFocus(doc, smooth);
@@ -141,15 +144,18 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                 this.layoutDoc._showSidebar = nativeWidth !== this.layoutDoc._nativeWidth;
             }
             return false;
-        }, emptyFunction, this.toggleSidebar);
+        }, emptyFunction, () => this.toggleSidebar());
     }
-    toggleSidebar = action(() => {
+    toggleSidebar = action((preview: boolean = false) => {
         const nativeWidth = NumCast(this.layoutDoc[this.fieldKey + "-nativeWidth"]);
         const ratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? 250 : 0) + nativeWidth) / nativeWidth;
         const curNativeWidth = NumCast(this.layoutDoc.nativeWidth, nativeWidth);
-        this.layoutDoc.nativeWidth = nativeWidth * ratio;
-        this.layoutDoc._width = this.layoutDoc[WidthSym]() * nativeWidth * ratio / curNativeWidth;
-        this.layoutDoc._showSidebar = nativeWidth !== this.layoutDoc._nativeWidth;
+        if (preview) this._showSidebar = true;
+        else {
+            this.layoutDoc.nativeWidth = nativeWidth * ratio;
+            this.layoutDoc._width = this.layoutDoc[WidthSym]() * nativeWidth * ratio / curNativeWidth;
+            this.layoutDoc._showSidebar = nativeWidth !== this.layoutDoc._nativeWidth;
+        }
     });
     settingsPanel() {
         const pageBtns = <>
@@ -202,7 +208,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                 </button>
             </div>;
     }
-    sidebarWidth = () => !this.layoutDoc._showSidebar ? 0 : (NumCast(this.layoutDoc.nativeWidth) - Doc.NativeWidth(this.dataDoc)) * this.props.PanelWidth() / NumCast(this.layoutDoc.nativeWidth);
+    sidebarWidth = () => !this.SidebarShown ? 0 : (NumCast(this.layoutDoc.nativeWidth) - Doc.NativeWidth(this.dataDoc)) * this.props.PanelWidth() / NumCast(this.layoutDoc.nativeWidth);
 
     specificContextMenu = (e: React.MouseEvent): void => {
         const funcs: ContextMenuProps[] = [];
@@ -223,6 +229,9 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     }
 
     anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick;
+    @observable _showSidebar = false;
+    @computed get SidebarShown() { return this._showSidebar || this.layoutDoc._showSidebar ? true : false; }
+
 
     @computed get renderPdfView() {
         TraceMobx();
@@ -255,6 +264,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                 rootDoc={this.rootDoc}
                 layoutDoc={this.layoutDoc}
                 dataDoc={this.dataDoc}
+                showSidebar={this.SidebarShown}
                 whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
                 sidebarAddDocument={this.sidebarAddDocument}
                 moveDocument={this.moveDocument}
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index f5b1f96f2..bb2c09fdf 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -160,6 +160,9 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     menuControls = () => this.urlEditor; // controls to be added to the top bar when a document of this type is selected
 
     scrollFocus = (doc: Doc, smooth: boolean) => {
+        if (DocListCast(this.props.Document[this.fieldKey + "-sidebar"]).includes(doc) && !this.SidebarShown) {
+            this.toggleSidebar(!smooth);
+        }
         if (this._sidebarRef?.current?.makeDocUnfiltered(doc)) return 1;
         if (doc !== this.rootDoc && this._outerRef.current) {
             const windowHeight = this.props.PanelHeight() / (this.props.scaling?.() || 1);
@@ -449,17 +452,20 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                 this.layoutDoc._showSidebar = nativeWidth !== this.layoutDoc._nativeWidth;
             }
             return false;
-        }, emptyFunction, this.toggleSidebar);
+        }, emptyFunction, () => this.toggleSidebar());
     }
-    toggleSidebar = action(() => {
+    toggleSidebar = action((preview: boolean = false) => {
         const nativeWidth = NumCast(this.layoutDoc[this.fieldKey + "-nativeWidth"]);
         const ratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? 250 : 0) + nativeWidth) / nativeWidth;
         const curNativeWidth = NumCast(this.layoutDoc.nativeWidth, nativeWidth);
-        this.layoutDoc.nativeWidth = nativeWidth * ratio;
-        this.layoutDoc._width = this.layoutDoc[WidthSym]() * nativeWidth * ratio / curNativeWidth;
-        this.layoutDoc._showSidebar = nativeWidth !== this.layoutDoc._nativeWidth;
+        if (preview) this._showSidebar;
+        else {
+            this.layoutDoc.nativeWidth = nativeWidth * ratio;
+            this.layoutDoc._width = this.layoutDoc[WidthSym]() * nativeWidth * ratio / curNativeWidth;
+            this.layoutDoc._showSidebar = nativeWidth !== this.layoutDoc._nativeWidth;
+        }
     });
-    sidebarWidth = () => !this.layoutDoc._showSidebar ? 0 : (NumCast(this.layoutDoc.nativeWidth) - Doc.NativeWidth(this.dataDoc)) * this.props.PanelWidth() / NumCast(this.layoutDoc.nativeWidth);
+    sidebarWidth = () => !this.SidebarShown ? 0 : (NumCast(this.layoutDoc.nativeWidth) - Doc.NativeWidth(this.dataDoc)) * this.props.PanelWidth() / NumCast(this.layoutDoc.nativeWidth);
 
     @computed get content() {
         return <div className={"webBox-cont" + (!this.props.docViewPath().lastElement()?.docView?._pendingDoubleClick && this.isContentActive() && CurrentUserUtils.SelectedTool === InkTool.None && !DocumentDecorations.Instance?.Interacting ? "-interactive" : "")}
@@ -475,7 +481,10 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                 <Annotation {...this.props} fieldKey={this.annotationKey} showInfo={this.showInfo} dataDoc={this.dataDoc} anno={anno} key={`${anno[Id]}-annotation`} />)
             }
         </div>;
+
     }
+    @observable _showSidebar = false;
+    @computed get SidebarShown() { return this._showSidebar || this.layoutDoc._showSidebar ? true : false; }
 
     showInfo = action((anno: Opt<Doc>) => this._overlayAnnoInfo = anno);
     setPreviewCursor = (func?: (x: number, y: number, drag: boolean) => void) => this._setPreviewCursor = func;
@@ -548,10 +557,11 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                 </div >
                 <SidebarAnnos ref={this._sidebarRef}
                     {...this.props}
-                    fieldKey={this.annotationKey}
+                    fieldKey={this.fieldKey}
                     rootDoc={this.rootDoc}
                     layoutDoc={this.layoutDoc}
                     dataDoc={this.dataDoc}
+                    showSidebar={this.SidebarShown}
                     sidebarAddDocument={this.sidebarAddDocument}
                     moveDocument={this.moveDocument}
                     removeDocument={this.removeDocument}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index f7e9ee028..d308345ec 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -120,7 +120,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     public get EditorView() { return this._editorView; }
     public get SidebarKey() { return this.fieldKey + "-sidebar"; }
 
-    @computed get sidebarWidthPercent() { return StrCast(this.layoutDoc._sidebarWidthPercent, "0%"); }
+    @computed get sidebarWidthPercent() { return this._showSidebar ? "20%" : StrCast(this.layoutDoc._sidebarWidthPercent, "0%"); }
     @computed get sidebarColor() { return StrCast(this.layoutDoc.sidebarColor, StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "#e4e4e4")); }
     @computed get autoHeight() { return this.layoutDoc._autoHeight && !this.props.ignoreAutoHeight; }
     @computed get textHeight() { return NumCast(this.rootDoc[this.fieldKey + "-height"]); }
@@ -544,11 +544,16 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         }
     }
 
+    @observable _showSidebar = false;
+    @computed get SidebarShown() { return this._showSidebar || this.layoutDoc._showSidebar ? true : false; }
+
     @action
-    toggleSidebar = () => {
+    toggleSidebar = (preview: boolean = false) => {
         const prevWidth = this.sidebarWidth();
-        this.layoutDoc._showSidebar = ((this.layoutDoc._sidebarWidthPercent = StrCast(this.layoutDoc._sidebarWidthPercent, "0%") === "0%" ? "50%" : "0%")) !== "0%";
-        this.layoutDoc._width = this.layoutDoc._showSidebar ? NumCast(this.layoutDoc._width) * 2 : Math.max(20, NumCast(this.layoutDoc._width) - prevWidth);
+        if (preview) this._showSidebar = true;
+        else this.layoutDoc._showSidebar = ((this.layoutDoc._sidebarWidthPercent = StrCast(this.layoutDoc._sidebarWidthPercent, "0%") === "0%" ? "50%" : "0%")) !== "0%";
+
+        this.layoutDoc._width = !preview && this.SidebarShown ? NumCast(this.layoutDoc._width) * 2 : Math.max(20, NumCast(this.layoutDoc._width) - prevWidth);
     }
     sidebarDown = (e: React.PointerEvent) => {
         setupMoveUpEvents(this, e, this.sidebarMove, emptyFunction, () => setTimeout(this.toggleSidebar), false);
@@ -726,6 +731,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     }
 
     scrollFocus = (textAnchor: Doc, smooth: boolean) => {
+        if (DocListCast(this.Document[this.fieldKey + "-sidebar"]).includes(textAnchor) && !this.SidebarShown) {
+            this.toggleSidebar(!smooth);
+        }
         const textAnchorId = textAnchor[Id];
         const findAnchorFrag = (frag: Fragment, editor: EditorView) => {
             const nodes: Node[] = [];
@@ -1468,10 +1476,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             return ComponentTag === CollectionStackingView ?
                 <SidebarAnnos ref={this._sidebarRef}
                     {...this.props}
-                    fieldKey={this.annotationKey}
+                    fieldKey={this.fieldKey}
                     rootDoc={this.rootDoc}
                     layoutDoc={this.layoutDoc}
                     dataDoc={this.dataDoc}
+                    showSidebar={this.SidebarShown}
                     PanelWidth={this.sidebarWidth}
                     setHeight={this.setSidebarHeight}
                     sidebarAddDocument={this.sidebarAddDocument}
@@ -1569,7 +1578,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                             }}
                         />
                     </div>
-                    {(this.props.noSidebar || this.Document._noSidebar) || this.props.dontSelectOnLoad || !this.layoutDoc._showSidebar || this.sidebarWidthPercent === "0%" ? (null) : this.sidebarCollection}
+                    {(this.props.noSidebar || this.Document._noSidebar) || this.props.dontSelectOnLoad || !this.SidebarShown || this.sidebarWidthPercent === "0%" ? (null) : this.sidebarCollection}
                     {(this.props.noSidebar || this.Document._noSidebar) || this.props.dontSelectOnLoad || this.Document._singleLine ? (null) : this.sidebarHandle}
                     {!this.layoutDoc._showAudio ? (null) : this.audioHandle}
                 </div>
-- 
cgit v1.2.3-70-g09d2


From 5550d58f16a0df090cde5a3605f6307b17e70758 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 5 Aug 2021 17:22:42 -0400
Subject: fixed so that links to sidebar annos show the sidebar in a
 LinkPreview

---
 src/client/views/SidebarAnnos.tsx                  |  3 +-
 src/client/views/collections/CollectionView.tsx    |  5 +-
 src/client/views/nodes/PDFBox.tsx                  | 68 ++++++++++++++--------
 src/client/views/nodes/WebBox.tsx                  | 35 ++++++-----
 .../views/nodes/formattedText/FormattedTextBox.tsx |  1 +
 src/client/views/pdf/PDFViewer.tsx                 |  2 -
 6 files changed, 70 insertions(+), 44 deletions(-)

(limited to 'src/client/views/nodes/PDFBox.tsx')

diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx
index f1d168a22..1f9763d18 100644
--- a/src/client/views/SidebarAnnos.tsx
+++ b/src/client/views/SidebarAnnos.tsx
@@ -24,6 +24,7 @@ interface ExtraProps {
     rootDoc: Doc;
     dataDoc: Doc;
     showSidebar: boolean;
+    nativeWidth: number;
     whenChildContentsActiveChanged: (isActive: boolean) => void;
     ScreenToLocalTransform: () => Transform;
     sidebarAddDocument: (doc: (Doc | Doc[]), suffix: string) => boolean;
@@ -76,7 +77,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
     get sidebarKey() { return this.props.fieldKey + "-sidebar"; }
     filtersHeight = () => 38;
     screenToLocalTransform = () => this.props.ScreenToLocalTransform().translate(Doc.NativeWidth(this.props.dataDoc), 0).scale(this.props.scaling?.() || 1);
-    panelWidth = () => !this.props.showSidebar ? 0 : this.props.layoutDoc.type === DocumentType.RTF ? this.props.PanelWidth() : (NumCast(this.props.layoutDoc.nativeWidth) - Doc.NativeWidth(this.props.dataDoc)) * this.props.PanelWidth() / NumCast(this.props.layoutDoc.nativeWidth);
+    panelWidth = () => !this.props.showSidebar ? 0 : this.props.layoutDoc.type === DocumentType.RTF ? this.props.PanelWidth() : (NumCast(this.props.nativeWidth) - Doc.NativeWidth(this.props.dataDoc)) * this.props.PanelWidth() / NumCast(this.props.nativeWidth);
     panelHeight = () => this.props.PanelHeight() - this.filtersHeight();
     addDocument = (doc: Doc | Doc[]) => this.props.sidebarAddDocument(doc, this.sidebarKey);
     moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument(doc, targetCollection, addDocument, this.sidebarKey);
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 2718cbbbf..2ae06d2f4 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -245,10 +245,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
         TraceMobx();
         const props: SubCollectionViewProps = {
             ...this.props,
-            SetSubView: action((subView: any) => {
-                console.log("Setting sub", subView);
-                return this._subView = subView
-            }),
+            SetSubView: action((subView: any) => this._subView = subView),
             addDocument: this.addDocument,
             moveDocument: this.moveDocument,
             removeDocument: this.removeDocument,
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index fc8fa4eef..b1f2070f8 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -9,7 +9,7 @@ import { makeInterface } from "../../../fields/Schema";
 import { Cast, NumCast, StrCast, BoolCast } from '../../../fields/Types';
 import { PdfField } from "../../../fields/URLField";
 import { TraceMobx } from '../../../fields/util';
-import { Utils, setupMoveUpEvents, emptyFunction } from '../../../Utils';
+import { Utils, setupMoveUpEvents, emptyFunction, returnOne } from '../../../Utils';
 import { Docs } from '../../documents/Documents';
 import { KeyCodes } from '../../util/KeyCodes';
 import { undoBatch } from '../../util/UndoManager';
@@ -31,6 +31,7 @@ const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema);
 @observer
 export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps, PdfDocument>(PdfDocument) {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PDFBox, fieldKey); }
+    public static openSidebarWidth = 250;
     private _searchString: string = "";
     private _initialScrollTarget: Opt<Doc>;
     private _pdfViewer: PDFViewer | undefined;
@@ -146,11 +147,17 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             return false;
         }, emptyFunction, () => this.toggleSidebar());
     }
+    @observable _previewNativeWidth: Opt<number> = undefined;
+    @observable _previewWidth: Opt<number> = undefined;
     toggleSidebar = action((preview: boolean = false) => {
         const nativeWidth = NumCast(this.layoutDoc[this.fieldKey + "-nativeWidth"]);
-        const ratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? 250 : 0) + nativeWidth) / nativeWidth;
+        const ratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? PDFBox.openSidebarWidth : 0) + nativeWidth) / nativeWidth;
         const curNativeWidth = NumCast(this.layoutDoc.nativeWidth, nativeWidth);
-        if (preview) this._showSidebar = true;
+        if (preview) {
+            this._previewNativeWidth = nativeWidth * ratio;
+            this._previewWidth = this.layoutDoc[WidthSym]() * nativeWidth * ratio / curNativeWidth;
+            this._showSidebar = true;
+        }
         else {
             this.layoutDoc.nativeWidth = nativeWidth * ratio;
             this.layoutDoc._width = this.layoutDoc[WidthSym]() * nativeWidth * ratio / curNativeWidth;
@@ -208,7 +215,9 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                 </button>
             </div>;
     }
-    sidebarWidth = () => !this.SidebarShown ? 0 : (NumCast(this.layoutDoc.nativeWidth) - Doc.NativeWidth(this.dataDoc)) * this.props.PanelWidth() / NumCast(this.layoutDoc.nativeWidth);
+    sidebarWidth = () => !this.SidebarShown ? 0 :
+        this._previewWidth ? PDFBox.openSidebarWidth :
+            (NumCast(this.layoutDoc.nativeWidth) - Doc.NativeWidth(this.dataDoc)) * this.props.PanelWidth() / NumCast(this.layoutDoc.nativeWidth);
 
     specificContextMenu = (e: React.MouseEvent): void => {
         const funcs: ContextMenuProps[] = [];
@@ -232,38 +241,51 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     @observable _showSidebar = false;
     @computed get SidebarShown() { return this._showSidebar || this.layoutDoc._showSidebar ? true : false; }
 
-
+    contentScaling = () => {
+        return 1;
+    }
     @computed get renderPdfView() {
         TraceMobx();
+        const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1;
+        const scale = previewScale * (this.props.scaling?.() || 1);
         return <div className={"pdfBox"} onContextMenu={this.specificContextMenu}
             style={{
                 height: this.props.Document._scrollTop && !this.Document._fitWidth && (window.screen.width > 600) ?
                     NumCast(this.Document._height) * this.props.PanelWidth() / NumCast(this.Document._width) : undefined
             }}>
             <div className="pdfBox-background" />
-            <PDFViewer {...this.props}
-                rootDoc={this.rootDoc}
-                layoutDoc={this.layoutDoc}
-                dataDoc={this.dataDoc}
-                pdf={this._pdf!}
-                url={this.pdfUrl!.url.pathname}
-                isContentActive={this.isContentActive}
-                anchorMenuClick={this.anchorMenuClick}
-                loaded={!Doc.NativeAspect(this.dataDoc) ? this.loaded : undefined}
-                setPdfViewer={this.setPdfViewer}
-                addDocument={this.addDocument}
-                moveDocument={this.moveDocument}
-                removeDocument={this.removeDocument}
-                whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
-                startupLive={true}
-                ContentScaling={this.props.scaling}
-                sidebarWidth={this.sidebarWidth}
-            />
+            <div style={{
+                width: `calc(${100 / scale}% - ${this.sidebarWidth() / scale * (this._previewWidth ? scale : 1)}px)`,
+                height: `${100 / scale}%`,
+                transform: `scale(${scale})`,
+                position: "absolute",
+                transformOrigin: "top left",
+                top: 0
+            }}>
+                <PDFViewer {...this.props}
+                    rootDoc={this.rootDoc}
+                    layoutDoc={this.layoutDoc}
+                    dataDoc={this.dataDoc}
+                    pdf={this._pdf!}
+                    url={this.pdfUrl!.url.pathname}
+                    isContentActive={this.isContentActive}
+                    anchorMenuClick={this.anchorMenuClick}
+                    loaded={!Doc.NativeAspect(this.dataDoc) ? this.loaded : undefined}
+                    setPdfViewer={this.setPdfViewer}
+                    addDocument={this.addDocument}
+                    moveDocument={this.moveDocument}
+                    removeDocument={this.removeDocument}
+                    whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
+                    startupLive={true}
+                    ContentScaling={returnOne}
+                />
+            </div>
             <SidebarAnnos ref={this._sidebarRef}
                 {...this.props}
                 rootDoc={this.rootDoc}
                 layoutDoc={this.layoutDoc}
                 dataDoc={this.dataDoc}
+                nativeWidth={this._previewNativeWidth ?? NumCast(this.layoutDoc._nativeWidth)}
                 showSidebar={this.SidebarShown}
                 whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
                 sidebarAddDocument={this.sidebarAddDocument}
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index bb2c09fdf..d2c806df6 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -43,6 +43,7 @@ const WebDocument = makeInterface(documentSchema);
 @observer
 export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps, WebDocument>(WebDocument) {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(WebBox, fieldKey); }
+    public static openSidebarWidth = 250;
     private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean) => void);
     private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
     private _outerRef: React.RefObject<HTMLDivElement> = React.createRef();
@@ -454,18 +455,27 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             return false;
         }, emptyFunction, () => this.toggleSidebar());
     }
+    @observable _previewNativeWidth: Opt<number> = undefined;
+    @observable _previewWidth: Opt<number> = undefined;
     toggleSidebar = action((preview: boolean = false) => {
         const nativeWidth = NumCast(this.layoutDoc[this.fieldKey + "-nativeWidth"]);
-        const ratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? 250 : 0) + nativeWidth) / nativeWidth;
+        const ratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? WebBox.openSidebarWidth : 0) + nativeWidth) / nativeWidth;
         const curNativeWidth = NumCast(this.layoutDoc.nativeWidth, nativeWidth);
-        if (preview) this._showSidebar;
+        if (preview) {
+            this._previewNativeWidth = nativeWidth * ratio;
+            this._previewWidth = this.layoutDoc[WidthSym]() * nativeWidth * ratio / curNativeWidth;
+            this._showSidebar = true;
+        }
         else {
             this.layoutDoc.nativeWidth = nativeWidth * ratio;
             this.layoutDoc._width = this.layoutDoc[WidthSym]() * nativeWidth * ratio / curNativeWidth;
             this.layoutDoc._showSidebar = nativeWidth !== this.layoutDoc._nativeWidth;
         }
     });
-    sidebarWidth = () => !this.SidebarShown ? 0 : (NumCast(this.layoutDoc.nativeWidth) - Doc.NativeWidth(this.dataDoc)) * this.props.PanelWidth() / NumCast(this.layoutDoc.nativeWidth);
+    sidebarWidth = () => !this.SidebarShown ? 0 :
+        this._previewWidth ? WebBox.openSidebarWidth :
+            (NumCast(this.layoutDoc.nativeWidth) - Doc.NativeWidth(this.dataDoc)) * this.props.PanelWidth() /
+            NumCast(this.layoutDoc.nativeWidth);
 
     @computed get content() {
         return <div className={"webBox-cont" + (!this.props.docViewPath().lastElement()?.docView?._pendingDoubleClick && this.isContentActive() && CurrentUserUtils.SelectedTool === InkTool.None && !DocumentDecorations.Instance?.Interacting ? "-interactive" : "")}
@@ -493,29 +503,25 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop));
     anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick;
     render() {
-        const inactiveLayer = this.props.layerProvider?.(this.layoutDoc) === false;
-        const scale = this.props.scaling?.() || 1;
+        const pointerEvents = this.props.layerProvider?.(this.layoutDoc) === false ? "none" : undefined;
+        const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1;
+        const scale = previewScale * (this.props.scaling?.() || 1);
         return (
             <div className="webBox" ref={this._mainCont} style={{ pointerEvents: this.isContentActive() ? "all" : this.isContentActive() || SnappingManager.GetIsDragging() ? undefined : "none" }} >
-                <div className={`webBox-container`}
-                    style={{ pointerEvents: inactiveLayer ? "none" : undefined }}
-                    onContextMenu={this.specificContextMenu}>
+                <div className={`webBox-container`} style={{ pointerEvents }} onContextMenu={this.specificContextMenu}>
                     <base target="_blank" />
                     <div className={"webBox-outerContent"} ref={this._outerRef}
                         style={{
-                            width: `calc(${100 / scale}% - ${this.sidebarWidth() / scale}px)`,
+                            width: `calc(${100 / scale}% - ${this.sidebarWidth() / scale * (this._previewWidth ? scale : 1)}px)`,
                             height: `${100 / scale}%`,
                             transform: `scale(${scale})`,
-                            pointerEvents: inactiveLayer ? "none" : undefined
+                            pointerEvents
                         }}
                         onWheel={e => { e.stopPropagation(); e.preventDefault(); }} // block wheel events from propagating since they're handled by the iframe
                         onScroll={e => this.setDashScrollTop(this._outerRef.current?.scrollTop || 0)}
                         onPointerDown={this.onMarqueeDown}
                     >
-                        <div className={"webBox-innerContent"} style={{
-                            height: NumCast(this.scrollHeight, 50),
-                            pointerEvents: inactiveLayer ? "none" : undefined
-                        }}>
+                        <div className={"webBox-innerContent"} style={{ height: NumCast(this.scrollHeight, 50), pointerEvents }}>
                             {this.content}
                             <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit}
                                 renderDepth={this.props.renderDepth + 1}
@@ -561,6 +567,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                     rootDoc={this.rootDoc}
                     layoutDoc={this.layoutDoc}
                     dataDoc={this.dataDoc}
+                    nativeWidth={this._previewNativeWidth ?? NumCast(this.layoutDoc._nativeWidth)}
                     showSidebar={this.SidebarShown}
                     sidebarAddDocument={this.sidebarAddDocument}
                     moveDocument={this.moveDocument}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index d308345ec..e5c36ea71 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1480,6 +1480,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                     rootDoc={this.rootDoc}
                     layoutDoc={this.layoutDoc}
                     dataDoc={this.dataDoc}
+                    nativeWidth={NumCast(this.layoutDoc._nativeWidth)}
                     showSidebar={this.SidebarShown}
                     PanelWidth={this.sidebarWidth}
                     setHeight={this.setSidebarHeight}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index e8c7a4ab0..e7911e8f8 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -46,7 +46,6 @@ interface IViewerProps extends FieldViewProps {
     loaded?: (nw: number, nh: number, np: number) => void;
     setPdfViewer: (view: PDFViewer) => void;
     ContentScaling?: () => number;
-    sidebarWidth: () => number;
     anchorMenuClick?: () => undefined | ((anchor: Doc) => void);
 }
 
@@ -550,7 +549,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
                 onScroll={this.onScroll} onWheel={this.onZoomWheel} onPointerDown={this.onPointerDown} onClick={this.onClick}
                 style={{
                     overflowX: this._zoomed !== 1 ? "scroll" : undefined,
-                    width: !this.props.Document._fitWidth && (window.screen.width > 600) ? Doc.NativeWidth(this.props.Document) - this.props.sidebarWidth() / this.contentScaling : `calc(${100 / this.contentScaling}% - ${this.props.sidebarWidth() / this.contentScaling}px)`,
                     height: !this.props.Document._fitWidth && (window.screen.width > 600) ? Doc.NativeHeight(this.props.Document) : `${100 / this.contentScaling}%`,
                     transform: `scale(${this.contentScaling})`
                 }}  >
-- 
cgit v1.2.3-70-g09d2


From d756ffd3daa24270361648454062e98f190ae964 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 6 Aug 2021 10:34:57 -0400
Subject: fixed webboxes so that you can link to an annotation and it will
 restore the url as well.   a bunch of warnings cleanup.

---
 src/client/util/DocumentManager.ts                        |  6 ++----
 src/client/views/DocumentButtonBar.tsx                    |  2 +-
 src/client/views/InkStrokeProperties.ts                   |  2 +-
 src/client/views/collections/CollectionSubView.tsx        |  2 +-
 src/client/views/collections/CollectionView.tsx           |  2 +-
 src/client/views/collections/TabDocView.tsx               |  4 ++--
 src/client/views/linking/LinkPopup.tsx                    |  1 -
 src/client/views/nodes/DocumentLinksButton.tsx            |  4 ++--
 src/client/views/nodes/PDFBox.tsx                         |  2 +-
 src/client/views/nodes/WebBox.tsx                         | 15 ++++++++++-----
 src/client/views/nodes/formattedText/FormattedTextBox.tsx |  1 -
 src/fields/Doc.ts                                         |  2 +-
 12 files changed, 22 insertions(+), 21 deletions(-)

(limited to 'src/client/views/nodes/PDFBox.tsx')

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 27ae0447a..cb0ee411c 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -163,7 +163,8 @@ export class DocumentManager {
         const contextDocs = docContext ? await DocListCastAsync(docContext.data) : undefined;
         const contextDoc = contextDocs?.find(doc => Doc.AreProtosEqual(doc, targetDoc) || Doc.AreProtosEqual(doc, annotatedDoc)) ? docContext : undefined;
         const targetDocContext = contextDoc || annotatedDoc;
-        var targetDocContextView = targetDocContext && getFirstDocView(targetDocContext);
+        const targetDocContextView = (targetDocContext && getFirstDocView(targetDocContext)) ||
+            (wasHidden && annoContainerView);// if we have an annotation container and the target was hidden, then try again because we just un-hid the document above
         const focusView = !docView && targetDoc.type === DocumentType.MARKER && annoContainerView ? annoContainerView : docView;
         if (!docView && annoContainerView) {
             annoContainerView.focus(targetDoc);  // this allows something like a PDF view to remove its doc filters to expose the target so that it can be found in the retry code below
@@ -181,9 +182,6 @@ export class DocumentManager {
             if (!targetDocContext) { // we don't have a view and there's no context specified ... create a new view of the target using the dockFunc or default
                 createViewFunc(Doc.BrushDoc(targetDoc), finished); // bcz: should we use this?: Doc.MakeAlias(targetDoc)));
             } else {  // otherwise try to get a view of the context of the target
-                if (annoContainerView && wasHidden) { // if we have an annotation container and the target was hidden, then try again because we just un-hid the document above
-                    targetDocContextView = annoContainerView;
-                }
                 if (targetDocContextView) { // we found a context view and aren't forced to create a new one ... focus on the context first..
                     targetDocContext._viewTransition = "transform 500ms";
                     targetDocContextView.props.focus(targetDocContextView.rootDoc, {
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index df1e6899d..5f09a322c 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -355,7 +355,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
             <div className="documentButtonBar-button">
                 <DocumentLinksButton View={this.view0} AlwaysOn={true} InMenu={true} StartLink={true} />
             </div>
-            {(DocumentLinksButton.StartLink || Doc.UserDoc()["documentLinksButton-fullMenu"]) && DocumentLinksButton.StartLink != doc ? <div className="documentButtonBar-button">
+            {(DocumentLinksButton.StartLink || Doc.UserDoc()["documentLinksButton-fullMenu"]) && DocumentLinksButton.StartLink !== doc ? <div className="documentButtonBar-button">
                 <DocumentLinksButton View={this.view0} AlwaysOn={true} InMenu={true} StartLink={false} />
             </div> : (null)}
             {/*!Doc.UserDoc()["documentLinksButton-fullMenu"] ? (null) : <div className="documentButtonBar-button">
diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts
index 76ca5b5ec..6444e4451 100644
--- a/src/client/views/InkStrokeProperties.ts
+++ b/src/client/views/InkStrokeProperties.ts
@@ -283,7 +283,7 @@ export class InkStrokeProperties {
      */
     @action
     rotatePoint = (target: PointData, origin: PointData, angle: number) => {
-        let rotatedTarget = { X: target.X - origin.X, Y: target.Y - origin.Y };
+        const rotatedTarget = { X: target.X - origin.X, Y: target.Y - origin.Y };
         const newX = Math.cos(angle) * rotatedTarget.X - Math.sin(angle) * rotatedTarget.Y;
         const newY = Math.sin(angle) * rotatedTarget.X + Math.cos(angle) * rotatedTarget.Y;
         rotatedTarget.X = newX + origin.X;
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index a9b5ce465..227635c9b 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -93,7 +93,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
         childDocFilters = () => [...this.props.docFilters(), ...this.collectionFilters()];
         childDocRangeFilters = () => [...(this.props.docRangeFilters?.() || []), ...this.collectionRangeDocFilters()];
         IsFiltered = () => this.collectionFilters().length || this.collectionRangeDocFilters().length ? "hasFilter" :
-            this.props.docFilters().length || this.props.docRangeFilters().length ? "inheritsFilter" : undefined;
+            this.props.docFilters().length || this.props.docRangeFilters().length ? "inheritsFilter" : undefined
         searchFilterDocs = () => this.props.searchFilterDocs?.() ?? DocListCast(this.props.Document._searchFilterDocs);
         @computed.struct get childDocs() {
             TraceMobx();
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 2ae06d2f4..e65ebf075 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -236,7 +236,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
     * Shows the filter icon if it's a user-created collection which isn't a dashboard and has some docFilters applied on it or on the current dashboard.
     */
     @computed get showFilterIcon() {
-        return this.props.Document.viewType !== CollectionViewType.Docking && !Doc.IsSystem(this.props.Document) && this._subView?.IsFiltered()
+        return this.props.Document.viewType !== CollectionViewType.Docking && !Doc.IsSystem(this.props.Document) && this._subView?.IsFiltered();
     }
 
     @observable _subView: any = undefined;
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 1f73793b6..1969d728c 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -172,8 +172,8 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             const stack: HTMLDivElement = tab.contentItem.parent;
             const header: HTMLDivElement = tab;
             stack.onscroll = action((e: any) => {
-                console.log('scrolling...')
-            })
+                console.log('scrolling...');
+            });
             const moreInfoDrag = document.createElement("div");
             moreInfoDrag.className = "lm_iconWrap";
             tab._disposers.buttonDisposer = reaction(() => this.view, view =>
diff --git a/src/client/views/linking/LinkPopup.tsx b/src/client/views/linking/LinkPopup.tsx
index 2c4b718f4..df469c53b 100644
--- a/src/client/views/linking/LinkPopup.tsx
+++ b/src/client/views/linking/LinkPopup.tsx
@@ -54,7 +54,6 @@ export class LinkPopup extends React.Component<LinkPopupProps> {
     @action
     onLinkChange = (e: React.ChangeEvent<HTMLInputElement>) => {
         this.linkURL = e.target.value;
-        console.log(this.linkURL)
     }
 
 
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index b63174e54..7648e866e 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -114,7 +114,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                     DocumentLinksButton.StartLink = this.props.View.props.Document;
                     DocumentLinksButton.StartLinkView = this.props.View;
                 }
-            };
+            }
         }));
     }
 
@@ -291,7 +291,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                         (null)
                 }
             </div>
-        )
+        );
     }
 
     render() {
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index b1f2070f8..23236cf20 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -217,7 +217,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     }
     sidebarWidth = () => !this.SidebarShown ? 0 :
         this._previewWidth ? PDFBox.openSidebarWidth :
-            (NumCast(this.layoutDoc.nativeWidth) - Doc.NativeWidth(this.dataDoc)) * this.props.PanelWidth() / NumCast(this.layoutDoc.nativeWidth);
+            (NumCast(this.layoutDoc.nativeWidth) - Doc.NativeWidth(this.dataDoc)) * this.props.PanelWidth() / NumCast(this.layoutDoc.nativeWidth)
 
     specificContextMenu = (e: React.MouseEvent): void => {
         const funcs: ContextMenuProps[] = [];
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 751d63711..ca281d68f 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -164,7 +164,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     menuControls = () => this.urlEditor; // controls to be added to the top bar when a document of this type is selected
 
     scrollFocus = (doc: Doc, smooth: boolean) => {
-        if (StrCast(doc.data) !== this._url) this.submitURL(StrCast(doc.data));
+        if (StrCast(doc.webUrl) !== this._url) this.submitURL(StrCast(doc.webUrl));
         if (DocListCast(this.props.Document[this.fieldKey + "-sidebar"]).includes(doc) && !this.SidebarShown) {
             this.toggleSidebar(!smooth);
         }
@@ -191,7 +191,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                 annotationOn: this.rootDoc,
                 y: NumCast(this.layoutDoc._scrollTop)
             });
-        this.addDocument(anchor);
+        this.addDocumentWrapper(anchor);
         return anchor;
     }
 
@@ -444,9 +444,14 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         return view;
     }
 
+    addDocumentWrapper = (doc: Doc | Doc[], annotationKey?: string) => {
+        (doc instanceof Doc ? [doc] : doc).forEach(doc => doc.webUrl = this._url);
+        return this.addDocument(doc, annotationKey);
+    }
+
     sidebarAddDocument = (doc: Doc | Doc[], sidebarKey?: string) => {
         if (!this.layoutDoc._showSidebar) this.toggleSidebar();
-        return this.addDocument(doc, sidebarKey);
+        return this.addDocumentWrapper(doc, sidebarKey);
     }
     sidebarBtnDown = (e: React.PointerEvent) => {
         setupMoveUpEvents(this, e, (e, down, delta) => {
@@ -482,7 +487,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     sidebarWidth = () => !this.SidebarShown ? 0 :
         this._previewWidth ? WebBox.openSidebarWidth :
             (NumCast(this.layoutDoc.nativeWidth) - Doc.NativeWidth(this.dataDoc)) * this.props.PanelWidth() /
-            NumCast(this.layoutDoc.nativeWidth);
+            NumCast(this.layoutDoc.nativeWidth)
 
     @computed get content() {
         return <div className={"webBox-cont" + (!this.props.docViewPath().lastElement()?.docView?._pendingDoubleClick && this.isContentActive() && CurrentUserUtils.SelectedTool === InkTool.None && !DocumentDecorations.Instance?.Interacting ? "-interactive" : "")}
@@ -561,7 +566,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                             anchorMenuClick={this.anchorMenuClick}
                             scrollTop={0}
                             down={this._marqueeing} scaling={returnOne}
-                            addDocument={this.addDocument}
+                            addDocument={this.addDocumentWrapper}
                             docView={this.props.docViewPath().lastElement()}
                             finishMarquee={this.finishMarquee}
                             savedAnnotations={this._savedAnnotations}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index e5c36ea71..edd7177de 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -215,7 +215,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         AnchorMenu.Instance.Status = "marquee";
         AnchorMenu.Instance.Highlight = action((color: string, isLinkButton: boolean) => {
             this._editorView?.state && RichTextMenu.Instance.insertHighlight(color, this._editorView.state, this._editorView?.dispatch);
-            console.log("highlight")
             return undefined;
         });
         /**
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 6dcf34a3a..0cbfaf067 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1214,7 +1214,7 @@ export namespace Doc {
             case DocumentType.RTF: return "sticky-note";
             case DocumentType.COL:
                 const folder: IconProp = isOpen ? "folder-open" : "folder";
-                const chevron: IconProp = isOpen ? "chevron-down" : "chevron-right"
+                const chevron: IconProp = isOpen ? "chevron-down" : "chevron-right";
                 return !doc?.isFolder ? folder : chevron;
             case DocumentType.WEB: return "globe-asia";
             case DocumentType.SCREENSHOT: return "photo-video";
-- 
cgit v1.2.3-70-g09d2


From 2d8b3c6b73da1b7685903697525a277fd53340a5 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 26 Aug 2021 00:32:47 -0400
Subject: a lot of changes to move isContentActive into DocumentView

---
 src/Utils.ts                                       |  2 +-
 src/client/views/DocComponent.tsx                  | 23 ++++++++----------
 src/client/views/collections/CollectionSubView.tsx |  3 +--
 src/client/views/collections/CollectionView.tsx    |  8 ++++++-
 src/client/views/collections/TabDocView.tsx        |  3 ++-
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 10 ++++----
 src/client/views/nodes/AudioBox.tsx                |  8 +++----
 .../views/nodes/CollectionFreeFormDocumentView.tsx |  6 +++--
 src/client/views/nodes/ComparisonBox.tsx           | 17 ++++++++++----
 src/client/views/nodes/DocumentView.tsx            | 15 ++++++++----
 src/client/views/nodes/ImageBox.tsx                |  3 +--
 src/client/views/nodes/PDFBox.tsx                  | 11 ++++-----
 src/client/views/nodes/VideoBox.tsx                | 27 +++++++++++-----------
 src/client/views/nodes/WebBox.tsx                  | 12 ++++------
 .../views/nodes/formattedText/FormattedTextBox.tsx | 10 ++++----
 src/client/views/pdf/AnchorMenu.tsx                |  1 -
 src/client/views/pdf/PDFViewer.tsx                 |  3 +--
 src/fields/Doc.ts                                  |  3 +++
 18 files changed, 91 insertions(+), 74 deletions(-)

(limited to 'src/client/views/nodes/PDFBox.tsx')

diff --git a/src/Utils.ts b/src/Utils.ts
index 102ac520b..de3b13f63 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -116,7 +116,7 @@ export namespace Utils {
     }
 
     const isTransparentFunctionHack = "isTransparent(__value__)";
-    const noRecursionHack = "__noRecursion";
+    export const noRecursionHack = "__noRecursion";
     export function IsRecursiveFilter(val: string) {
         return !val.includes(noRecursionHack);
     }
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index d9cc29bed..33dff9da5 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -1,17 +1,17 @@
-import { Doc, Opt, DataSym, AclReadonly, AclAugment, AclPrivate, AclEdit, AclSym, DocListCast, AclAdmin, AclSelfEdit } from '../../fields/Doc';
-import { Touchable } from './Touchable';
-import { computed, action, observable } from 'mobx';
-import { Cast, BoolCast, ScriptCast } from '../../fields/Types';
+import { action, computed, observable } from 'mobx';
+import { DateField } from '../../fields/DateField';
+import { AclAdmin, AclAugment, AclEdit, AclPrivate, AclReadonly, AclSym, DataSym, Doc, DocListCast, Opt } from '../../fields/Doc';
 import { InkTool } from '../../fields/InkField';
-import { InteractionUtils } from '../util/InteractionUtils';
 import { List } from '../../fields/List';
-import { DateField } from '../../fields/DateField';
 import { ScriptField } from '../../fields/ScriptField';
-import { GetEffectiveAcl, SharingPermissions, distributeAcls, denormalizeEmail, inheritParentAcls } from '../../fields/util';
-import { CurrentUserUtils } from '../util/CurrentUserUtils';
-import { DocUtils } from '../documents/Documents';
+import { Cast, ScriptCast } from '../../fields/Types';
+import { denormalizeEmail, distributeAcls, GetEffectiveAcl, inheritParentAcls, SharingPermissions } from '../../fields/util';
 import { returnFalse } from '../../Utils';
+import { DocUtils } from '../documents/Documents';
+import { CurrentUserUtils } from '../util/CurrentUserUtils';
+import { InteractionUtils } from '../util/InteractionUtils';
 import { UndoManager } from '../util/UndoManager';
+import { Touchable } from './Touchable';
 
 
 ///  DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView)
@@ -107,6 +107,7 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
         // key where data is stored
         @computed get fieldKey() { return this.props.fieldKey; }
 
+        isAnyChildContentActive = () => this._isAnyChildContentActive;
 
         lookupField = (field: string) => ScriptCast((this.layoutDoc as any).lookupField)?.script.run({ self: this.layoutDoc, data: this.rootDoc, field: field }).result;
 
@@ -229,10 +230,6 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
         }
 
         whenChildContentsActiveChanged = action((isActive: boolean) => this.props.whenChildContentsActiveChanged(this._isAnyChildContentActive = isActive));
-        isContentActive = (outsideReaction?: boolean) => (CurrentUserUtils.SelectedTool !== InkTool.None ||
-            (this.props.isContentActive?.() || this.props.Document.forceActive ||
-                this.props.isSelected(outsideReaction) || this._isAnyChildContentActive ||
-                this.props.rootSelected(outsideReaction)) ? true : false)
     }
     return Component;
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 1f4c35daa..b70df93da 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -23,6 +23,7 @@ import ReactLoading from 'react-loading';
 export interface SubCollectionViewProps extends CollectionViewProps {
     CollectionView: Opt<CollectionView>;
     SetSubView?: (subView: any) => void;
+    isAnyChildContentActive: () => boolean;
 }
 
 export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: X) {
@@ -490,7 +491,5 @@ import { FormattedTextBox, GoogleRef } from "../nodes/formattedText/FormattedTex
 import { CollectionView, CollectionViewType, CollectionViewProps } from "./CollectionView";
 import { SelectionManager } from "../../util/SelectionManager";
 import { OverlayView } from "../OverlayView";
-import { Hypothesis } from "../../util/HypothesisUtils";
 import { GetEffectiveAcl, TraceMobx } from "../../../fields/util";
-import { FilterBox } from "../nodes/FilterBox";
 
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index a821aeeea..229e93b9e 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -37,6 +37,7 @@ import { CollectionTreeView } from "./CollectionTreeView";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import './CollectionView.scss';
 import { returnEmptyString } from '../../../Utils';
+import { InkTool } from '../../../fields/InkField';
 export const COLLECTION_BORDER_WIDTH = 2;
 const path = require('path');
 
@@ -119,7 +120,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
         // const imageProtos = children.filter(doc => Cast(doc.data, ImageField)).map(Doc.GetProto);
         // const allTagged = imageProtos.length > 0 && imageProtos.every(image => image.googlePhotosTags);
         // return !allTagged ? (null) : <img id={"google-tags"} src={"/assets/google_tags.png"} />;
-        this.isContentActive();
+        //this.isContentActive();
     }
 
     screenToLocalTransform = () => this.props.renderDepth ? this.props.ScreenToLocalTransform() : this.props.ScreenToLocalTransform().scale(this.props.PanelWidth() / this.bodyPanelWidth());
@@ -253,6 +254,9 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
 
     @observable _subView: any = undefined;
 
+    isContentActive = (outsideReaction?: boolean) => {
+        return this.props.isContentActive() ? true : false;
+    }
     render() {
         TraceMobx();
         const props: SubCollectionViewProps = {
@@ -262,6 +266,8 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
             moveDocument: this.moveDocument,
             removeDocument: this.removeDocument,
             isContentActive: this.isContentActive,
+            isAnyChildContentActive: this.isAnyChildContentActive,
+            whenChildContentsActiveChanged: this.whenChildContentsActiveChanged,
             PanelWidth: this.bodyPanelWidth,
             PanelHeight: this.props.PanelHeight,
             ScreenToLocalTransform: this.screenToLocalTransform,
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index e24fcf372..117dba4de 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -480,7 +480,8 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
                     childLayoutTemplate={this.childLayoutTemplate} // bcz: Ugh .. should probably be rendering a CollectionView or the minimap should be part of the collectionFreeFormView to avoid having to set stuff like this.
                     noOverlay={true} // don't render overlay Docs since they won't scale
                     setHeight={returnFalse}
-                    isContentActive={returnTrue}
+                    isContentActive={returnFalse}
+                    isAnyChildContentActive={returnFalse}
                     select={emptyFunction}
                     dropAction={undefined}
                     isSelected={returnFalse}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index b5d9ebd9f..fb949a36d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,6 +1,7 @@
 import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
 import { computedFn } from "mobx-utils";
+import { DateField } from "../../../../fields/DateField";
 import { Doc, HeightSym, Opt, StrListCast, WidthSym } from "../../../../fields/Doc";
 import { collectionSchema, documentSchema } from "../../../../fields/documentSchemas";
 import { Id } from "../../../../fields/FieldSymbols";
@@ -17,6 +18,7 @@ import { aggregateBounds, emptyFunction, intersectRect, returnFalse, setupMoveUp
 import { CognitiveServices } from "../../../cognitive_services/CognitiveServices";
 import { DocServer } from "../../../DocServer";
 import { Docs, DocUtils } from "../../../documents/Documents";
+import { DocumentType } from "../../../documents/DocumentTypes";
 import { CurrentUserUtils } from "../../../util/CurrentUserUtils";
 import { DocumentManager } from "../../../util/DocumentManager";
 import { DragManager, dropActionType } from "../../../util/DragManager";
@@ -48,8 +50,7 @@ import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCurso
 import "./CollectionFreeFormView.scss";
 import { MarqueeView } from "./MarqueeView";
 import React = require("react");
-import { DocumentType } from "../../../documents/DocumentTypes";
-import { DateField } from "../../../../fields/DateField";
+import Color = require("color");
 
 export const panZoomSchema = createSchema({
     _panX: "number",
@@ -117,7 +118,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
 
     @computed get views() { return this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z).map(ele => ele.ele); }
     @computed get backgroundEvents() { return this.props.layerProvider?.(this.layoutDoc) === false && SnappingManager.GetIsDragging(); }
-    @computed get backgroundActive() { return this.props.layerProvider?.(this.layoutDoc) === false && (this.props.ContainingCollectionView?.isContentActive() || this.props.isContentActive()); }
+    @computed get backgroundActive() { return this.props.layerProvider?.(this.layoutDoc) === false && this.props.isContentActive(); }
     @computed get fitToContentVals() {
         return {
             bounds: { ...this.contentBounds, cx: (this.contentBounds.x + this.contentBounds.r) / 2, cy: (this.contentBounds.y + this.contentBounds.b) / 2 },
@@ -170,6 +171,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     getContainerTransform = () => this.cachedGetContainerTransform.copy();
     getTransformOverlay = () => this.getContainerTransform().translate(1, 1);
     getActiveDocuments = () => this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => pair.layout);
+    isAnyChildContentActive = () => this.props.isAnyChildContentActive();
     addLiveTextBox = (newBox: Doc) => {
         FormattedTextBox.SelectOnLoad = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed
         this.addDocument(newBox);
@@ -1033,7 +1035,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             docFilters={this.childDocFilters}
             docRangeFilters={this.childDocRangeFilters}
             searchFilterDocs={this.searchFilterDocs}
-            isContentActive={this.isAnnotationOverlay ? this.props.isContentActive : returnFalse}
+            isContentActive={returnFalse}
             isDocumentActive={this.props.childDocumentsActive ? this.props.isDocumentActive : this.isContentActive}
             focus={this.focusDocument}
             addDocTab={this.addDocTab}
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 82bad971d..faaa887c4 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -267,7 +267,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
 
     // returns the html audio element
     @computed get audio() {
-        return <audio ref={this.setRef} className={`audiobox-control${this.isContentActive() ? "-interactive" : ""}`}>
+        return <audio ref={this.setRef} className={`audiobox-control${this.props.isContentActive() ? "-interactive" : ""}`}>
             <source src={this.path} type="audio/mpeg" />
             Not supported.
         </audio>;
@@ -328,6 +328,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
             focus={DocUtils.DefaultFocus}
             bringToFront={emptyFunction}
             CollectionView={undefined}
+            isAnyChildContentActive={this.isAnyChildContentActive}
             duration={this.duration}
             playFrom={this.playFrom}
             setTime={this.setAnchorTime}
@@ -337,7 +338,6 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
             ScreenToLocalTransform={this.timelineScreenToLocal}
             Play={this.Play}
             Pause={this.Pause}
-            isContentActive={this.isContentActive}
             playLink={this.playLink}
             PanelWidth={this.timelineWidth}
             PanelHeight={this.timelineHeight}
@@ -345,7 +345,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     }
 
     render() {
-        const interactive = SnappingManager.GetIsDragging() || this.isContentActive() ? "-interactive" : "";
+        const interactive = SnappingManager.GetIsDragging() || this.props.isContentActive() ? "-interactive" : "";
         return <div className="audiobox-container"
             onContextMenu={this.specificContextMenu}
             onClick={!this.path && !this._recorder ? this.recordAudioAnnotation : undefined}
@@ -370,7 +370,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
                             RECORD
                         </button>}
                 </div> :
-                <div className="audiobox-controls" style={{ pointerEvents: this._isAnyChildContentActive || this.isContentActive() ? "all" : "none" }} >
+                <div className="audiobox-controls" style={{ pointerEvents: this._isAnyChildContentActive || this.props.isContentActive() ? "all" : "none" }} >
                     <div className="audiobox-dictation" />
                     <div className="audiobox-player" style={{ height: `${AudioBox.heightPercent}%` }} >
                         <div className="audiobox-playhead" style={{ width: AudioBox.playheadWidth }} title={this.mediaState === "paused" ? "play" : "pause"} onClick={this.Play}> <FontAwesomeIcon style={{ width: "100%", position: "absolute", left: "0px", top: "5px", borderWidth: "thin", borderColor: "white" }} icon={this.mediaState === "paused" ? "play" : "pause"} size={"1x"} /></div>
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 092823603..9cc4b1f9a 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -17,8 +17,8 @@ import { InkingStroke } from "../InkingStroke";
 import { StyleProp } from "../StyleProvider";
 import "./CollectionFreeFormDocumentView.scss";
 import { DocumentView, DocumentViewProps } from "./DocumentView";
-import { FieldViewProps } from "./FieldView";
 import React = require("react");
+import Color = require("color");
 
 export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
     dataProvider?: (doc: Doc, replica: string) => { x: number, y: number, zIndex?: number, opacity?: number, highlight?: boolean, z: number, transition?: string } | undefined;
@@ -164,6 +164,8 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
             PanelWidth: this.panelWidth,
             PanelHeight: this.panelHeight,
         };
+        const background = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+        const mixBlendMode = StrCast(this.layoutDoc.mixBlendMode) as any || (background && Color(background).alpha() !== 1 ? "multiply" : undefined);
         return <div className={"collectionFreeFormDocumentView-container"}
             style={{
                 outline: this.Highlight ? "orange solid 2px" : "",
@@ -172,7 +174,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                 transform: this.transform,
                 transition: this.props.dataTransition ? this.props.dataTransition : this.dataProvider ? this.dataProvider.transition : StrCast(this.layoutDoc.dataTransition),
                 zIndex: this.ZInd,
-                mixBlendMode: StrCast(this.layoutDoc.mixBlendMode) as any,
+                mixBlendMode,
                 display: this.ZInd === -99 ? "none" : undefined
             }} >
             <DocumentView {...divProps} ref={action((r: DocumentView | null) => this._contentView = r)} />
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index 153176afc..6708a08ee 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -1,17 +1,18 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, observable } from 'mobx';
 import { observer } from "mobx-react";
-import { Doc } from '../../../fields/Doc';
+import { Doc, Opt } from '../../../fields/Doc';
 import { documentSchema } from '../../../fields/documentSchemas';
 import { createSchema, makeInterface } from '../../../fields/Schema';
 import { Cast, NumCast, StrCast } from '../../../fields/Types';
-import { emptyFunction, OmitKeys, setupMoveUpEvents } from '../../../Utils';
+import { emptyFunction, OmitKeys, returnFalse, setupMoveUpEvents } from '../../../Utils';
 import { DragManager } from '../../util/DragManager';
 import { SnappingManager } from '../../util/SnappingManager';
 import { undoBatch } from '../../util/UndoManager';
 import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent';
+import { StyleProp } from '../StyleProvider';
 import "./ComparisonBox.scss";
-import { DocumentView } from './DocumentView';
+import { DocumentView, DocumentViewProps } from './DocumentView';
 import { FieldView, FieldViewProps } from './FieldView';
 import React = require("react");
 
@@ -71,6 +72,11 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
         delete this.dataDoc[fieldKey];
     }
 
+    docStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string): any => {
+        if (property === StyleProp.PointerEvents) return "none";
+        return this.props.styleProvider?.(doc, props, property);
+    }
+
     render() {
         const clipWidth = NumCast(this.layoutDoc._clipWidth) + "%";
         const clearButton = (which: string) => {
@@ -84,6 +90,9 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
             const whichDoc = Cast(this.dataDoc[`compareBox-${which}`], Doc, null);
             return whichDoc ? <>
                 <DocumentView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
+                    isContentActive={returnFalse}
+                    isDocumentActive={returnFalse}
+                    styleProvider={this.docStyleProvider}
                     Document={whichDoc}
                     DataDoc={undefined}
                     pointerEvents={"none"} />
@@ -102,7 +111,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
         };
 
         return (
-            <div className={`comparisonBox${this.isContentActive() || SnappingManager.GetIsDragging() ? "-interactive" : ""}` /* change className to easily disable/enable pointer events in CSS */}>
+            <div className={`comparisonBox${this.props.isContentActive() || SnappingManager.GetIsDragging() ? "-interactive" : ""}` /* change className to easily disable/enable pointer events in CSS */}>
                 {displayBox("after", 1, this.props.PanelWidth() - 3)}
                 <div className="clip-div" style={{ width: clipWidth, transition: this._animating, background: StrCast(this.layoutDoc._backgroundColor, "gray") }}>
                     {displayBox("before", 0, 0)}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index bb259da3e..11fb5cdb3 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -84,6 +84,7 @@ export interface DocComponentView {
     reverseNativeScaling?: () => boolean; // DocumentView's setup screenToLocal based on the doc having a nativeWidth/Height.  However, some content views (e.g., FreeFormView w/ fitToBox set) may ignore the native dimensions so this flags the DocumentView to not do Nativre scaling.
     shrinkWrap?: () => void;  // requests a document to display all of its contents with no white space.  currently only implemented (needed?) for freeform views
     menuControls?: () => JSX.Element; // controls to display in the top menu bar when the document is selected.
+    isAnyChildContentActive?: () => boolean; // is any child content of the document active
     getKeyFrameEditing?: () => boolean; // whether the document is in keyframe editing mode (if it is, then all hidden documents that are not active at the keyframe time will still be shown)
     setKeyFrameEditing?: (set: boolean) => void; // whether the document is in keyframe editing mode (if it is, then all hidden documents that are not active at the keyframe time will still be shown)
     playFrom?: (time: number, endTime?: number) => void;
@@ -182,7 +183,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
     private _dropDisposer?: DragManager.DragDropDisposer;
     private _holdDisposer?: InteractionUtils.MultiTouchEventDisposer;
     protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer;
-    _componentView: Opt<DocComponentView>; // needs to be accessed from DocumentView wrapper class
+    @observable _componentView: Opt<DocComponentView>; // needs to be accessed from DocumentView wrapper class
 
     private get topMost() { return this.props.renderDepth === 0 && !LightboxView.LightboxDoc; }
     public get displayName() { return "DocumentView(" + this.props.Document.title + ")"; } // this makes mobx trace() statements more descriptive
@@ -778,8 +779,14 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
     contentScaling = () => this.ContentScale;
     onClickFunc = () => this.onClickHandler;
     setHeight = (height: number) => this.layoutDoc._height = height;
-    setContentView = (view: { getAnchor?: () => Doc, forward?: () => boolean, back?: () => boolean }) => this._componentView = view;
-    isContentActive = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || this.props.isContentActive() ? true : false;
+    setContentView = action((view: { getAnchor?: () => Doc, forward?: () => boolean, back?: () => boolean }) => this._componentView = view);
+    isContentActive = (outsideReaction?: boolean) => {
+        return CurrentUserUtils.SelectedTool !== InkTool.None ||
+            this.props.Document.forceActive ||
+            this.props.isSelected(outsideReaction) ||
+            this._componentView?.isAnyChildContentActive?.() ||
+            this.props.isContentActive() ? true : false;
+    }
     @computed get contents() {
         TraceMobx();
         const audioView = !this.layoutDoc._showAudio ? (null) :
@@ -794,7 +801,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             </div>;
         return <div className="documentView-contentsView"
             style={{
-                pointerEvents: (this.props.contentPointerEvents as any) || (CurrentUserUtils.SelectedTool !== InkTool.None || SnappingManager.GetIsDragging() || this.isContentActive() ? "all" : "none"),
+                pointerEvents: (this.props.contentPointerEvents as any) || (this.isContentActive() ? "all" : "none"),
                 height: this.headerMargin ? `calc(100% - ${this.headerMargin}px)` : undefined,
             }}>
             <DocumentContentsView key={1} {...this.props}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index c4e74ebd2..b392ddb95 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -332,7 +332,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         return <div className="imageBox-annotationLayer" style={{ height: this.props.PanelHeight() }} ref={this._annotationLayer} />;
     }
     marqueeDown = (e: React.PointerEvent) => {
-        if (!e.altKey && e.button === 0 && this.layoutDoc._viewScale === 1 && this.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) {
+        if (!e.altKey && e.button === 0 && this.layoutDoc._viewScale === 1 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) {
             setupMoveUpEvents(this, e, action(e => {
                 MarqueeAnnotator.clearAnnotations(this._savedAnnotations)
                 this._marqueeing = [e.clientX, e.clientY];
@@ -368,7 +368,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
                 ScreenToLocalTransform={this.screenToLocalTransform}
                 scaling={returnOne}
                 select={emptyFunction}
-                isContentActive={this.isContentActive}
                 whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
                 removeDocument={this.removeDocument}
                 moveDocument={this.moveDocument}
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 23236cf20..341fa5919 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -177,9 +177,9 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         </>;
         const searchTitle = `${!this._searching ? "Open" : "Close"} Search Bar`;
         const curPage = this.Document._curPage || 1;
-        return !this.isContentActive() ? (null) :
+        return !this.props.isContentActive() ? (null) :
             <div className="pdfBox-ui" onKeyDown={e => [KeyCodes.BACKSPACE, KeyCodes.DELETE].includes(e.keyCode) ? e.stopPropagation() : true}
-                onPointerDown={e => e.stopPropagation()} style={{ display: this.isContentActive() ? "flex" : "none" }}>
+                onPointerDown={e => e.stopPropagation()} style={{ display: this.props.isContentActive() ? "flex" : "none" }}>
                 <div className="pdfBox-overlayCont" onPointerDown={(e) => e.stopPropagation()} style={{ left: `${this._searching ? 0 : 100}%` }}>
                     <button className="pdfBox-overlayButton" title={searchTitle} />
                     <input className="pdfBox-searchBar" placeholder="Search" ref={this._searchRef} onChange={this.searchStringChanged}
@@ -209,7 +209,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                     {this._pageControls ? pageBtns : (null)}
                 </div>
                 <button className="pdfBox-sidebarBtn" title="Toggle Sidebar"
-                    style={{ display: !this.isContentActive() ? "none" : undefined }}
+                    style={{ display: !this.props.isContentActive() ? "none" : undefined }}
                     onPointerDown={this.sidebarBtnDown} >
                     <FontAwesomeIcon icon={"chevron-left"} size="sm" />
                 </button>
@@ -229,7 +229,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     }
 
     @computed get renderTitleBox() {
-        const classname = "pdfBox" + (this.isContentActive() ? "-interactive" : "");
+        const classname = "pdfBox" + (this.props.isContentActive() ? "-interactive" : "");
         return <div className={classname} >
             <div className="pdfBox-title-outer">
                 <strong className="pdfBox-title" >{this.props.Document.title}</strong>
@@ -268,7 +268,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                     dataDoc={this.dataDoc}
                     pdf={this._pdf!}
                     url={this.pdfUrl!.url.pathname}
-                    isContentActive={this.isContentActive}
+                    isContentActive={this.props.isContentActive}
                     anchorMenuClick={this.anchorMenuClick}
                     loaded={!Doc.NativeAspect(this.dataDoc) ? this.loaded : undefined}
                     setPdfViewer={this.setPdfViewer}
@@ -291,7 +291,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                 sidebarAddDocument={this.sidebarAddDocument}
                 moveDocument={this.moveDocument}
                 removeDocument={this.removeDocument}
-                isContentActive={this.isContentActive}
             />
             {this.settingsPanel()}
         </div>;
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index d4df30b48..484dec7e2 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -307,7 +307,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         const interactive = CurrentUserUtils.SelectedTool !== InkTool.None || !this.props.isSelected() ? "" : "-interactive";
         const style = "videoBox-content" + (this._fullScreen ? "-fullScreen" : "") + interactive;
         return !field ? <div key="loading">Loading</div> :
-            <div className="container" key="container" style={{ pointerEvents: this._isAnyChildContentActive || this.isContentActive() ? "all" : "none" }}>
+            <div className="container" key="container" style={{ mixBlendMode: "multiply", pointerEvents: this.props.isContentActive() ? "all" : "none" }}>
                 <div className={`${style}`} style={{ width: "100%", height: "100%", left: "0px" }}>
                     <video key="video" autoPlay={this._screenCapture} ref={this.setVideoRef}
                         style={{ height: "100%", width: "auto", display: "flex", margin: "auto" }}
@@ -321,7 +321,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
                         Not supported.
                     </video>
                     {!this.audiopath || this.audiopath === field.url.href ? (null) :
-                        <audio ref={this.setAudioRef} className={`audiobox-control${this.isContentActive() ? "-interactive" : ""}`}>
+                        <audio ref={this.setAudioRef} className={`audiobox-control${this.props.isContentActive() ? "-interactive" : ""}`}>
                             <source src={this.audiopath} type="audio/mpeg" />
                         Not supported.
                     </audio>}
@@ -378,30 +378,30 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     private get uIButtons() {
         const curTime = (this.layoutDoc._currentTimecode || 0);
         const nonNativeControls = [
-            <Tooltip title={<div className="dash-tooltip">{"playback"}</div>} placement="bottom">
-                <div className="videoBox-play" key="play" onPointerDown={this.onPlayDown} >
+            <Tooltip title={<div className="dash-tooltip">{"playback"}</div>} key="play" placement="bottom">
+                <div className="videoBox-play" onPointerDown={this.onPlayDown} >
                     <FontAwesomeIcon icon={this._playing ? "pause" : "play"} size="lg" />
                 </div>
             </Tooltip>,
-            <Tooltip title={<div className="dash-tooltip">{"timecode"}</div>} placement="bottom">
+            <Tooltip title={<div className="dash-tooltip">{"timecode"}</div>} key="time" placement="bottom">
                 <div className="videoBox-time" onPointerDown={this.onResetDown} >
                     <span>{formatTime(curTime)}</span>
                     <span style={{ fontSize: 8 }}>{" " + Math.floor((curTime - Math.trunc(curTime)) * 100).toString().padStart(2, "0")}</span>
                 </div>
             </Tooltip>,
-            <Tooltip title={<div className="dash-tooltip">{"view full screen"}</div>} placement="bottom">
+            <Tooltip title={<div className="dash-tooltip">{"view full screen"}</div>} key="full" placement="bottom">
                 <div className="videoBox-full" onPointerDown={this.FullScreen}>
                     <FontAwesomeIcon icon="expand" size="lg" />
                 </div>
             </Tooltip>];
         return <div className="videoBox-ui">
             {[...(VideoBox._nativeControls ? [] : nonNativeControls),
-            <Tooltip title={<div className="dash-tooltip">{"snapshot current frame"}</div>} placement="bottom">
+            <Tooltip title={<div className="dash-tooltip">{"snapshot current frame"}</div>} key="snap" placement="bottom">
                 <div className="videoBox-snapshot" onPointerDown={this.onSnapshotDown} >
                     <FontAwesomeIcon icon="camera" size="lg" />
                 </div>
             </Tooltip>,
-            <Tooltip title={<div className="dash-tooltip">{"show annotation timeline"}</div>} placement="bottom">
+            <Tooltip title={<div className="dash-tooltip">{"show annotation timeline"}</div>} key="timeline" placement="bottom">
                 <div className="videoBox-timelineButton" onPointerDown={this.onTimelineHdlDown}>
                     <FontAwesomeIcon icon="eye" size="lg" />
                 </div>
@@ -429,7 +429,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         setupMoveUpEvents(this, e,
             action((e: PointerEvent) => {
                 this._clicking = false;
-                if (this.isContentActive()) {
+                if (this.props.isContentActive()) {
                     const local = this.props.ScreenToLocalTransform().scale(this.props.scaling?.() || 1).transformPoint(e.clientX, e.clientY);
                     this.layoutDoc._timelineHeightPercent = Math.max(0, Math.min(100, local[1] / this.props.PanelHeight() * 100));
                 }
@@ -438,7 +438,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
             () => {
                 this.layoutDoc._timelineHeightPercent = this.heightPercent !== 100 ? 100 : VideoBox.heightPercent;
                 setTimeout(action(() => this._clicking = false), 500);
-            }, this.isContentActive(), this.isContentActive());
+            }, this.props.isContentActive(), this.props.isContentActive());
     });
 
     onResetDown = (e: React.PointerEvent) => {
@@ -529,12 +529,12 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
                 playFrom={this.playFrom}
                 setTime={this.setAnchorTime}
                 playing={this.playing}
+                isAnyChildContentActive={this.isAnyChildContentActive}
                 whenChildContentsActiveChanged={this.timelineWhenChildContentsActiveChanged}
                 removeDocument={this.removeDocument}
                 ScreenToLocalTransform={this.timelineScreenToLocal}
                 Play={this.Play}
                 Pause={this.Pause}
-                isContentActive={this.isContentActive}
                 playLink={this.playLink}
                 PanelHeight={this.timelineHeight}
             />
@@ -546,7 +546,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     }
 
     marqueeDown = (e: React.PointerEvent) => {
-        if (!e.altKey && e.button === 0 && this.layoutDoc._viewScale === 1 && this.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) {
+        if (!e.altKey && e.button === 0 && this.layoutDoc._viewScale === 1 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) {
             setupMoveUpEvents(this, e, action(e => {
                 MarqueeAnnotator.clearAnnotations(this._savedAnnotations);
                 this._marqueeing = [e.clientX, e.clientY];
@@ -570,7 +570,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     }
     marqueeFitScaling = () => (this.props.scaling?.() || 1) * this.heightPercent / 100;
     marqueeOffset = () => [this.panelWidth() / 2 * (1 - this.heightPercent / 100) / (this.heightPercent / 100), 0];
-    timelineDocFilter = () => ["_timelineLabel:true:x"];
+    timelineDocFilter = () => [`_timelineLabel:true,${Utils.noRecursionHack}:x`];
     render() {
         const borderRad = this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BorderRounding);
         const borderRadius = borderRad?.includes("px") ? `${Number(borderRad.split("px")[0]) / this.scaling()}px` : borderRad;
@@ -592,7 +592,6 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
                         ScreenToLocalTransform={this.screenToLocalTransform}
                         docFilters={this.timelineDocFilter}
                         select={emptyFunction}
-                        isContentActive={this.isContentActive}
                         scaling={returnOne}
                         whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
                         removeDocument={this.removeDocument}
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index ae6b90e41..b484ce302 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -401,7 +401,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
 
     @action
     onMarqueeDown = (e: React.PointerEvent) => {
-        if (!e.altKey && e.button === 0 && this.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) {
+        if (!e.altKey && e.button === 0 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) {
             setupMoveUpEvents(this, e, action(e => {
                 MarqueeAnnotator.clearAnnotations(this._savedAnnotations);
                 this._marqueeing = [e.clientX, e.clientY];
@@ -484,7 +484,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             NumCast(this.layoutDoc.nativeWidth)
 
     @computed get content() {
-        return <div className={"webBox-cont" + (!this.props.docViewPath().lastElement()?.docView?._pendingDoubleClick && this.isContentActive() && CurrentUserUtils.SelectedTool === InkTool.None && !DocumentDecorations.Instance?.Interacting ? "-interactive" : "")}
+        return <div className={"webBox-cont" + (!this.props.docViewPath().lastElement()?.docView?._pendingDoubleClick && this.props.isContentActive() && CurrentUserUtils.SelectedTool === InkTool.None && !DocumentDecorations.Instance?.Interacting ? "-interactive" : "")}
             style={{ width: NumCast(this.layoutDoc[this.fieldKey + "-contentWidth"]) || `${100 / (this.props.scaling?.() || 1)}%`, }}>
             {this.urlContent}
         </div>;
@@ -529,7 +529,6 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                 docFilters={docFilters || this.props.docFilters}
                 dontRenderDocuments={docFilters ? false : true}
                 select={emptyFunction}
-                isContentActive={returnFalse}
                 ContentScaling={returnOne}
                 bringToFront={emptyFunction}
                 whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
@@ -539,7 +538,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                 childPointerEvents={true}
                 pointerEvents={CurrentUserUtils.SelectedTool !== InkTool.None || this._isAnnotating || SnappingManager.GetIsDragging() ? "all" : "none"} />;
         return (
-            <div className="webBox" ref={this._mainCont} style={{ pointerEvents: this.isContentActive() ? "all" : this.isContentActive() || SnappingManager.GetIsDragging() ? undefined : "none" }} >
+            <div className="webBox" ref={this._mainCont} style={{ pointerEvents: this.props.isContentActive() ? "all" : this.props.isContentActive() || SnappingManager.GetIsDragging() ? undefined : "none" }} >
                 <div className={`webBox-container`} style={{ pointerEvents }} onContextMenu={this.specificContextMenu}>
                     <base target="_blank" />
                     <div className={"webBox-outerContent"} ref={this._outerRef}
@@ -559,7 +558,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                                 {renderAnnotations(this.transparentFilter)}
                             </div>
                             {renderAnnotations(this.opaqueFilter)}
-                            {renderAnnotations()}
+                            {SnappingManager.GetIsDragging() ? (null) : renderAnnotations()}
                             {this.annotationLayer}
                         </div>
                     </div>
@@ -588,10 +587,9 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                     sidebarAddDocument={this.sidebarAddDocument}
                     moveDocument={this.moveDocument}
                     removeDocument={this.removeDocument}
-                    isContentActive={this.isContentActive}
                 />
                 <button className="webBox-overlayButton-sidebar" key="sidebar" title="Toggle Sidebar"
-                    style={{ display: !this.isContentActive() ? "none" : undefined }}
+                    style={{ display: !this.props.isContentActive() ? "none" : undefined }}
                     onPointerDown={this.sidebarBtnDown} >
                     <FontAwesomeIcon style={{ color: "white" }} icon={"chevron-left"} size="sm" />
                 </button>
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index d1027dfd7..4b1d76d00 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1211,7 +1211,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         if ((e.nativeEvent as any).formattedHandled) {
             console.log("handled");
         }
-        if (!(e.nativeEvent as any).formattedHandled && this.isContentActive(true)) {
+        if (!(e.nativeEvent as any).formattedHandled && this.props.isContentActive(true)) {
             const editor = this._editorView!;
             const pcords = editor.posAtCoords({ left: e.clientX, top: e.clientY });
             !this.props.isSelected(true) && editor.dispatch(editor.state.tr.setSelection(new TextSelection(editor.state.doc.resolve(pcords?.pos || 0))));
@@ -1481,7 +1481,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     @computed get sidebarHandle() {
         TraceMobx();
         const annotated = DocListCast(this.dataDoc[this.SidebarKey]).filter(d => d?.author).length;
-        return (!annotated && !this.isContentActive()) ? (null) : <div className="formattedTextBox-sidebar-handle" onPointerDown={this.sidebarDown}
+        return (!annotated && !this.props.isContentActive()) ? (null) : <div className="formattedTextBox-sidebar-handle" onPointerDown={this.sidebarDown}
             style={{
                 left: `max(0px, calc(100% - ${this.sidebarWidthPercent} ${this.sidebarWidth() ? "- 5px" : "- 10px"}))`,
                 background: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.WidgetColor + (annotated ? ":annotated" : ""))
@@ -1504,7 +1504,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                     sidebarAddDocument={this.sidebarAddDocument}
                     moveDocument={this.moveDocument}
                     removeDocument={this.removeDocument}
-                    isContentActive={this.isContentActive}
                 /> :
                 <ComponentTag
                     {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit}
@@ -1517,7 +1516,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                     scaleField={this.SidebarKey + "-scale"}
                     isAnnotationOverlay={false}
                     select={emptyFunction}
-                    isContentActive={this.isContentActive}
                     scaling={this.sidebarContentScaling}
                     whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
                     removeDocument={this.sidebarRemDocument}
@@ -1539,7 +1537,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     render() {
         TraceMobx();
         const selected = this.props.isSelected();
-        const active = this.isContentActive();
+        const active = this.props.isContentActive();
         const scale = this.props.hideOnLeave ? 1 : (this.props.scaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1);
         const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : "";
         const interactive = (CurrentUserUtils.SelectedTool === InkTool.None || SnappingManager.GetIsDragging()) && (this.layoutDoc.z || this.props.layerProvider?.(this.layoutDoc) !== false);
@@ -1551,7 +1549,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         const selPaddingClass = selected && !this.layoutDoc._singleLine && margins >= 10 ? "-selected" : "";
         return (
             <div className="formattedTextBox-cont"
-                onWheel={e => this.isContentActive() && e.stopPropagation()}
+                onWheel={e => this.props.isContentActive() && e.stopPropagation()}
                 style={{
                     transform: this.props.dontScale ? undefined : `scale(${scale})`,
                     transformOrigin: this.props.dontScale ? undefined : "top left",
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index 75e3f81fb..42bec38da 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -69,7 +69,6 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
         this._disposer = reaction(() => SelectionManager.Views(),
             selected => {
                 this._showLinkPopup = false;
-                console.log("unmount");
                 AnchorMenu.Instance.fadeOut(true)
             });
     }
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 734d9127c..bc35d2126 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -512,7 +512,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
         const renderAnnotations = (docFilters?: () => string[]) =>
             <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit}
                 isAnnotationOverlay={true}
-                isContentActive={returnFalse}
                 fieldKey={this.props.fieldKey + "-annotations"}
                 setPreviewCursor={this.setPreviewCursor}
                 PanelHeight={this.panelHeight}
@@ -543,7 +542,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
                     transform: `scale(${this._zoomed})`
                 }}>
                 {renderAnnotations(this.opaqueFilter)}
-                {renderAnnotations()}
+                {SnappingManager.GetIsDragging() ? (null) : renderAnnotations()}
             </div>
         </div>;
     }
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 17f41fac8..b09ff93d0 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1092,6 +1092,9 @@ export namespace Doc {
             const isTransparent = (color: string) => color !== "" && (Color(color).alpha() !== 1);
             return isTransparent(StrCast(doc[key]));
         }
+        if (typeof value === "string") {
+            value = value.replace(`,${Utils.noRecursionHack}`, "");
+        }
         const fieldVal = doc[key];
         if (Cast(fieldVal, listSpec("string"), []).length) {
             const vals = Cast(fieldVal, listSpec("string"), []);
-- 
cgit v1.2.3-70-g09d2


From 7c83bc30b3a6ed6061ef68bcef6a0e8941668b3c Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 26 Aug 2021 19:17:53 -0400
Subject: fixed resizing bug for web and pdf documents when doing autoheight
 gesture, and after opening the sidebar and then resizing

---
 src/client/documents/Documents.ts                       | 10 ++++++++++
 src/client/views/collections/CollectionStackingView.tsx |  2 +-
 src/client/views/nodes/PDFBox.tsx                       |  1 +
 src/client/views/nodes/WebBox.tsx                       | 14 ++++++++------
 src/client/views/pdf/PDFViewer.tsx                      |  8 +++++---
 5 files changed, 25 insertions(+), 10 deletions(-)

(limited to 'src/client/views/nodes/PDFBox.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index db1e67203..a1ffddb98 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -709,10 +709,20 @@ export namespace Docs {
         }
 
         export function PdfDocument(url: string, options: DocumentOptions = {}) {
+            const width = options._width || undefined;
+            const height = options._height || undefined;
+            const nwid = options._nativeWidth || undefined;
+            const nhght = options._nativeHeight || undefined;
+            if (!nhght && width && height && nwid) options._nativeHeight = Number(nwid) * Number(height) / Number(width);
             return InstanceFromProto(Prototypes.get(DocumentType.PDF), new PdfField(url), options);
         }
 
         export function WebDocument(url: string, options: DocumentOptions = {}) {
+            const width = options._width || undefined;
+            const height = options._height || undefined;
+            const nwid = options._nativeWidth || undefined;
+            const nhght = options._nativeHeight || undefined;
+            if (!nhght && width && height && nwid) options._nativeHeight = Number(nwid) * Number(height) / Number(width);
             return InstanceFromProto(Prototypes.get(DocumentType.WEB), url ? new WebField(url) : undefined, options);
         }
 
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index b9bc83d49..4fedda1bd 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -144,7 +144,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
             () => this.layoutDoc._columnHeaders = new List()
         );
         this._autoHeightDisposer = reaction(() => this.layoutDoc._autoHeight,
-            () => this.props.setHeight(Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER),
+            autoHeight => autoHeight && this.props.setHeight(Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER),
                 this.headerMargin + (this.isStackingView ?
                     Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace("px", "")))) :
                     this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0)))));
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 341fa5919..5e07229c1 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -285,6 +285,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                 rootDoc={this.rootDoc}
                 layoutDoc={this.layoutDoc}
                 dataDoc={this.dataDoc}
+                setHeight={emptyFunction}
                 nativeWidth={this._previewNativeWidth ?? NumCast(this.layoutDoc._nativeWidth)}
                 showSidebar={this.SidebarShown}
                 whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index b484ce302..e4d4557af 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -88,12 +88,13 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             this.dataDoc[this.fieldKey + "-sidebar"] = ComputedField.MakeFunction(`copyField(this["${this.fieldKey}-"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"-sidebar"`);
         });
 
-        this._disposers.selection = reaction(() => this.props.isSelected(),
-            selected => !selected && setTimeout(() => {
-                // Array.from(this._savedAnnotations.values()).forEach(v => v.forEach(a => a.remove()));
-                // this._savedAnnotations.clear();
-            })
-        );
+        this._disposers.autoHeight = reaction(() => this.layoutDoc._autoHeight,
+            autoHeight => {
+                if (autoHeight) {
+                    this.layoutDoc._nativeHeight = NumCast(this.props.Document[this.props.fieldKey + "-nativeHeight"]);
+                    this.props.setHeight(NumCast(this.props.Document[this.props.fieldKey + "-nativeHeight"]) * (this.props.scaling?.() || 1));
+                }
+            });
 
         if (this.webField?.href.indexOf("youtube") !== -1) {
             const youtubeaspect = 400 / 315;
@@ -582,6 +583,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                     rootDoc={this.rootDoc}
                     layoutDoc={this.layoutDoc}
                     dataDoc={this.dataDoc}
+                    setHeight={emptyFunction}
                     nativeWidth={this._previewNativeWidth ?? NumCast(this.layoutDoc._nativeWidth)}
                     showSidebar={this.SidebarShown}
                     sidebarAddDocument={this.sidebarAddDocument}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index e77fdde3d..02010e123 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -119,9 +119,11 @@ export class PDFViewer extends React.Component<IViewerProps> {
         this._mainCont.current?.addEventListener("scroll", e => (e.target as any).scrollLeft = 0);
 
         this._disposers.autoHeight = reaction(() => this.props.layoutDoc._autoHeight,
-            () => {
-                this.props.layoutDoc._nativeHeight = NumCast(this.props.Document[this.props.fieldKey + "-nativeHeight"]);
-                this.props.setHeight(NumCast(this.props.Document[this.props.fieldKey + "-nativeHeight"]) * (this.props.scaling?.() || 1));
+            autoHeight => {
+                if (autoHeight) {
+                    this.props.layoutDoc._nativeHeight = NumCast(this.props.Document[this.props.fieldKey + "-nativeHeight"]);
+                    this.props.setHeight(NumCast(this.props.Document[this.props.fieldKey + "-nativeHeight"]) * (this.props.scaling?.() || 1));
+                }
             });
 
         this._disposers.searchMatch = reaction(() => Doc.IsSearchMatch(this.props.rootDoc),
-- 
cgit v1.2.3-70-g09d2

