From feac7f17533c4b587cadc783fbd5f47c464d40db Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 26 Feb 2021 02:24:32 -0500
Subject: updated fieldInfos a bit more.

---
 src/client/views/collections/TabDocView.tsx | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

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

diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 3f8794665..68ca93f43 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -382,7 +382,8 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
         }
     }
     @computed get renderBounds() {
-        const bounds = this.props.tabView()?.ComponentView?.freeformData?.(true)?.bounds;
+        const compView = this.props.tabView()?.ComponentView as CollectionFreeFormView;
+        const bounds = compView?.freeformData?.(true)?.bounds;
         if (!bounds) return undefined;
         const xbounds = bounds.r - bounds.x;
         const ybounds = bounds.b - bounds.y;
-- 
cgit v1.2.3-70-g09d2


From 7902b1021b89e45bd595e4a9588db11dccbf9831 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sun, 28 Feb 2021 01:06:27 -0500
Subject: a bunch of changes to simplify how autoHeight works.  extended to
 work for pdfs and stacking views.  still some bugs.

---
 src/client/documents/Documents.ts                  |   2 +-
 src/client/util/CurrentUserUtils.ts                |   2 +-
 src/client/views/DocComponent.tsx                  |   2 +-
 src/client/views/DocumentDecorations.tsx           |  30 ++--
 src/client/views/MainView.tsx                      |   4 +
 src/client/views/TemplateMenu.tsx                  |   1 +
 .../views/collections/CollectionSchemaView.tsx     |   2 +-
 .../views/collections/CollectionStackingView.tsx   |  17 +-
 src/client/views/collections/TabDocView.tsx        |   1 +
 src/client/views/nodes/DocumentContentsView.tsx    |   1 +
 src/client/views/nodes/DocumentView.tsx            |  16 +-
 src/client/views/nodes/FieldView.tsx               |   3 +-
 src/client/views/nodes/FilterBox.tsx               |   1 +
 src/client/views/nodes/KeyValuePair.tsx            |   1 +
 .../views/nodes/formattedText/FormattedTextBox.tsx | 180 ++++++---------------
 src/client/views/pdf/PDFViewer.tsx                 |   6 +
 src/client/views/search/SearchBox.tsx              |   2 +-
 17 files changed, 108 insertions(+), 163 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index d725e5fc9..7f20fa990 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -240,7 +240,7 @@ export class DocumentOptions {
     treeViewDefaultExpandedView?: string; // default expanded view
     sidebarColor?: string;  // background color of text sidebar
     sidebarViewType?: string; // collection type of text sidebar
-    docMaxHeight?: number; // maximum height for newly created (eg, from pasting) text documents
+    docMaxAutoHeight?: number; // maximum height for newly created (eg, from pasting) text documents
     textTransform?: string; // is linear view expanded
     letterSpacing?: string; // is linear view expanded
     flexDirection?: "unset" | "row" | "column" | "row-reverse" | "column-reverse";
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index eab372d5d..3304de9a1 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -1198,7 +1198,7 @@ export class CurrentUserUtils {
 
     public static GetNewTextDoc(title: string, x: number, y: number, width?: number, height?: number, noMargins?: boolean, annotationOn?: Doc, maxHeight?: number) {
         const tbox = Docs.Create.TextDocument("", {
-            _xMargin: noMargins ? 0 : undefined, _yMargin: noMargins ? 0 : undefined, annotationOn, docMaxHeight: maxHeight,
+            _xMargin: noMargins ? 0 : undefined, _yMargin: noMargins ? 0 : undefined, annotationOn, docMaxAutoHeight: maxHeight,
             _width: width || 200, _height: height || 100, x: x, y: y, _autoHeight: true, _fontSize: StrCast(Doc.UserDoc().fontSize),
             _fontFamily: StrCast(Doc.UserDoc().fontFamily), title
         });
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index ef1228976..128ba858f 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -11,7 +11,7 @@ import { GetEffectiveAcl, SharingPermissions, distributeAcls, denormalizeEmail }
 
 
 ///  DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView)
-interface DocComponentProps {
+export interface DocComponentProps {
     Document: Doc;
     LayoutTemplate?: () => Opt<Doc>;
     LayoutTemplateString?: string;
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 2391a21e6..f41238228 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -369,8 +369,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
         let dX = 0, dY = 0, dW = 0, dH = 0;
         const unfreeze = () =>
             SelectionManager.Views().forEach(action((element: DocumentView) =>
-                ((element.rootDoc.type === DocumentType.RTF ||
-                    element.rootDoc.type === DocumentType.COMPARISON ||
+                ((element.rootDoc.type === DocumentType.COMPARISON ||
                     (element.rootDoc.type === DocumentType.WEB && Doc.LayoutField(element.rootDoc) instanceof HtmlField))
                     && Doc.NativeHeight(element.layoutDoc)) && element.toggleNativeDimensions()));
         switch (this._resizeHdlId) {
@@ -431,7 +430,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
                     if (nwidth / nheight !== width / height && !dragBottom) {
                         height = nheight / nwidth * width;
                     }
-                    if (e.ctrlKey || (!dragBottom || !docView.layoutDoc._fitWidth)) { // ctrl key enables modification of the nativeWidth or nativeHeight durin the interaction
+                    if (e.ctrlKey && !dragBottom) { // ctrl key enables modification of the nativeWidth or nativeHeight durin the interaction
                         if (Math.abs(dW) > Math.abs(dH)) dH = dW * nheight / nwidth;
                         else dW = dH * nwidth / nheight;
                     }
@@ -441,10 +440,6 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
                 doc.x = (doc.x || 0) + dX * (actualdW - width);
                 doc.y = (doc.y || 0) + dY * (actualdH - height);
                 const fixedAspect = (nwidth && nheight);
-                if (fixedAspect && (!nwidth || !nheight)) {
-                    doc._nativeWidth = nwidth = doc._width || 0;
-                    doc._nativeHeight = nheight = doc._height || 0;
-                }
                 if (e.ctrlKey && [DocumentType.IMG, DocumentType.SCREENSHOT, DocumentType.VID].includes(doc.type as DocumentType)) {
                     dW !== 0 && runInAction(() => {
                         const dataDoc = doc[DataSym];
@@ -454,22 +449,24 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
                         Doc.SetNativeHeight(dataDoc, nh + (dW > 0 ? 10 : -10) * nh / nw);
                     });
                 }
-                else if (nwidth > 0 && nheight > 0) {
-                    if (Math.abs(dW) > Math.abs(dH) || dragRight) {
-                        if (!fixedAspect || (dragRight && e.ctrlKey)) {
+                else if (fixedAspect) {
+                    if ((Math.abs(dW) > Math.abs(dH) && (!dragBottom || !e.ctrlKey)) || dragRight) {
+                        if (dragRight && e.ctrlKey) {
                             doc._nativeWidth = actualdW / (doc._width || 1) * Doc.NativeWidth(doc);
+                        } else {
+                            if (!doc._fitWidth) doc._height = nheight / nwidth * actualdW;
+                            else if (!e.ctrlKey) doc._height = actualdH;
                         }
                         doc._width = actualdW;
-                        if (fixedAspect && !doc._fitWidth) doc._height = nheight / nwidth * doc._width;
-                        else if (!fixedAspect || !e.ctrlKey) doc._height = actualdH;
                     }
                     else {
-                        if (!fixedAspect || (dragBottom && (e.ctrlKey || docView.layoutDoc._fitWidth))) {
+                        if (dragBottom && (e.ctrlKey || docView.layoutDoc._fitWidth)) { // frozen web pages and others that fitWidth can't grow horizontally to match a vertical resize so the only choice is to change the nativeheight even if the ctrl key isn't used
                             doc._nativeHeight = actualdH / (doc._height || 1) * Doc.NativeHeight(doc);
+                        } else {
+                            if (!doc._fitWidth) doc._width = nwidth / nheight * actualdH;
+                            else if (!e.ctrlKey) doc._width = actualdW;
                         }
                         doc._height = actualdH;
-                        if (fixedAspect && !doc._fitWidth) doc._width = nwidth / nheight * doc._height;
-                        else if (!fixedAspect || !e.ctrlKey) doc._width = actualdW;
                     }
                 } else {
                     dW && (doc._width = actualdW);
@@ -486,7 +483,8 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
         SelectionManager.Views().map(dv => {
             if (NumCast(dv.layoutDoc._delayAutoHeight) < this._dragHeights.get(dv.layoutDoc)!) {
                 dv.nativeWidth > 0 && Doc.toggleNativeDimensions(dv.layoutDoc, dv.ContentScale(), dv.props.PanelWidth(), dv.props.PanelHeight());
-                dv.layoutDoc._autoHeight = true;
+                if (dv.layoutDoc._autoHeight) dv.layoutDoc._autoHeight = false;
+                setTimeout(() => dv.layoutDoc._autoHeight = true);
             }
             dv.layoutDoc._delayAutoHeight = undefined;
         });
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 01afed5f9..b0c0af002 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -482,6 +482,7 @@ export class MainView extends React.Component {
                     DataDoc={undefined}
                     fieldKey={"data"}
                     dropAction={"alias"}
+                    setHeight={returnFalse}
                     parentActive={returnFalse}
                     styleProvider={DefaultStyleProvider}
                     layerProvider={undefined}
@@ -552,6 +553,7 @@ export class MainView extends React.Component {
                 isSelected={returnTrue}
                 active={returnTrue}
                 select={returnTrue}
+                setHeight={returnFalse}
                 addDocument={undefined}
                 addDocTab={this.addDocTabFunc}
                 pinToPres={emptyFunction}
@@ -589,6 +591,7 @@ export class MainView extends React.Component {
                     styleProvider={undefined}
                     isSelected={returnFalse}
                     select={returnFalse}
+                    setHeight={returnFalse}
                     rootSelected={returnFalse}
                     renderDepth={0}
                     parentActive={returnFalse}
@@ -661,6 +664,7 @@ export class MainView extends React.Component {
                             select={returnFalse}
                             rootSelected={returnFalse}
                             renderDepth={0}
+                            setHeight={returnFalse}
                             layerProvider={undefined}
                             styleProvider={undefined}
                             addDocTab={returnFalse}
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index d2e0cb265..f39d5ee4c 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -140,6 +140,7 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
                 rootSelected={returnFalse}
                 onCheckedClick={this.scriptField}
                 onChildClick={this.scriptField}
+                setHeight={returnFalse}
                 dropAction={undefined}
                 active={returnTrue}
                 parentActive={returnFalse}
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 504cf32a0..a265045b8 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -553,7 +553,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         </div>;
         return <div className={"collectionSchemaView" + (this.props.Document._searchDoc ? "-searchContainer" : "-container")}
             style={{
-                overflow: this.props.overflow === true ? "scroll" : undefined, backgroundColor: "white",
+                overflow: this.props.scrollOverflow === true ? "scroll" : undefined, backgroundColor: "white",
                 pointerEvents: this.props.Document._searchDoc !== undefined && !this.props.active() && !SnappingManager.GetIsDragging() ? "none" : undefined,
                 width: name === "collectionSchemaView-searchContainer" ? "auto" : this.props.PanelWidth() || "100%", height: this.props.PanelHeight() || "100%", position: "relative",
             }}  >
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 77046f5ea..b5ce4b443 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -140,8 +140,10 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
             () => this.pivotField,
             () => this.layoutDoc._columnHeaders = new List()
         );
-        this._autoHeightDisposer = reaction(() => this.layoutDoc._autoHeight, this.forceAutoHeight);
+        this._autoHeightDisposer = reaction(() => this.layoutDoc._autoHeight,
+            () => this.props.setHeight(this.headerMargin + this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0)));
     }
+
     componentWillUnmount() {
         super.componentWillUnmount();
         this._pivotFieldDisposer?.();
@@ -369,11 +371,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
                             const height = this.headerMargin +
                                 Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER),
                                     Math.max(...this.refList.map(r => NumCast(Doc.Layout(doc)._viewScale, 1) * Number(getComputedStyle(r).height.replace("px", "")))));
-                            if (this.props.isAnnotationOverlay) {
-                                doc[this.props.fieldKey + "-height"] = height;
-                            } else {
-                                Doc.Layout(doc)._height = height * NumCast(Doc.Layout(doc)._viewScale, 1);
-                            }
+                            this.props.setHeight(height * NumCast(Doc.Layout(doc)._viewScale, 1));
                         }
                     }));
                     this.observer.observe(ref);
@@ -398,11 +396,6 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
         return new Transform(-translateX, -translateY, 1).scale(this.props.ScreenToLocalTransform().Scale);
     }
 
-    forceAutoHeight = () => {
-        const doc = this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc;
-        Doc.Layout(doc)._height = this.headerMargin + this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0);
-    }
-
     sectionMasonry = (heading: SchemaHeaderField | undefined, docList: Doc[], first: boolean) => {
         const key = this.pivotField;
         let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined;
@@ -422,7 +415,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
                     this.observer = new _global.ResizeObserver(action((entries: any) => {
                         if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) {
                             const height = this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0);
-                            Doc.Layout(doc)._height = this.headerMargin + Math.max(height, NumCast(doc[this.props.fieldKey + "-height"]));
+                            this.props.setHeight(this.headerMargin + height);
                         }
                     }));
                     this.observer.observe(ref);
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 68ca93f43..f7e067399 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -420,6 +420,7 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
                     docViewPath={returnEmptyDoclist}
                     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}
                     active={returnTrue}
                     select={emptyFunction}
                     dropAction={undefined}
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 7a8eb5628..c0af1e08a 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -109,6 +109,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & Fo
     isSelected: (outsideReaction: boolean) => boolean,
     select: (ctrl: boolean) => void,
     scaling?: () => number,
+    setHeight: (height: number) => void,
     layoutKey: string,
     hideOnLeave?: boolean,
 }> {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index a48bc8f87..761485d61 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,5 +1,5 @@
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { action, computed, observable, runInAction } from "mobx";
+import { action, computed, observable, runInAction, reaction, IReactionDisposer } from "mobx";
 import { observer } from "mobx-react";
 import { AclAdmin, AclEdit, AclPrivate, DataSym, Doc, DocListCast, Field, Opt, StrListCast } from "../../../fields/Doc";
 import { Document } from '../../../fields/documentSchemas';
@@ -753,6 +753,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
     screenToLocal = () => this.props.ScreenToLocalTransform().translate(0, -this.headerMargin);
     contentScaling = () => this.ContentScale;
     onClickFunc = () => this.onClickHandler;
+    setHeight = (height: number) => this.rootDoc._height = height;
     setContentView = (view: { getAnchor?: () => Doc, forward?: () => boolean, back?: () => boolean }) => this._componentView = view;
     @observable contentsActive: () => boolean = returnFalse;
     @action setContentsActive = (setActive: () => boolean) => this.contentsActive = setActive;
@@ -778,6 +779,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                 setContentView={this.setContentView}
                 scaling={this.contentScaling}
                 PanelHeight={this.panelHeight}
+                setHeight={this.setHeight}
                 contentsActive={this.setContentsActive}
                 parentActive={this.parentActive}
                 ScreenToLocalTransform={this.screenToLocal}
@@ -974,6 +976,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     public static ROOT_DIV = "documentView-effectsWrapper";
     public get displayName() { return "DocumentView(" + this.props.Document?.title + ")"; } // this makes mobx trace() statements more descriptive
     public ContentRef = React.createRef<HTMLDivElement>();
+    private _disposers: { [name: string]: IReactionDisposer } = {};
 
     @observable public docView: DocumentViewInternal | undefined | null;
 
@@ -1070,9 +1073,20 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     }
 
     componentDidMount() {
+        this._disposers.height = reaction(
+            () => NumCast(this.layoutDoc._height),
+            action(height => {
+                const docMax = NumCast(this.layoutDoc.docMaxAutoHeight);
+                if (docMax && docMax < height) this.layoutDoc.docMaxAutoHeight = height;
+                if (height && height <= 20 && height < NumCast(this.layoutDoc._delayAutoHeight, 20)) {
+                    this.layoutDoc._delayAutoHeight = height;
+                }
+            })
+        );
         !BoolCast(this.props.Document.dontRegisterView, this.props.dontRegisterView) && DocumentManager.Instance.AddView(this);
     }
     componentWillUnmount() {
+        Object.values(this._disposers).forEach(disposer => disposer?.());
         !this.props.dontRegisterView && DocumentManager.Instance.RemoveView(this);
     }
 
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 1b4119210..465c18309 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -16,12 +16,13 @@ import { VideoBox } from "./VideoBox";
 export interface FieldViewProps extends DocumentViewSharedProps {
     // FieldView specific props that are not part of DocumentView props
     fieldKey: string;
-    overflow?: boolean; // bcz: would like to think this can be avoided -- need to look at further
+    scrollOverflow?: boolean; // bcz: would like to think this can be avoided -- need to look at further
 
     active: (outsideReaction?: boolean) => boolean;
     select: (isCtrlPressed: boolean) => void;
     isSelected: (outsideReaction?: boolean) => boolean;
     scaling?: () => number;
+    setHeight: (height: number) => void;
 
     // properties intended to be used from within layout strings (otherwise use the function equivalents that work more efficiently with React)
     pointerEvents?: string;
diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index f42f487cf..bdd9334f4 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -185,6 +185,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
                     fieldKey={this.props.fieldKey}
                     CollectionView={undefined}
                     cantBrush={true}
+                    setHeight={returnFalse} // if the tree view can trigger the height of the filter box to change, then this needs to be filled in.
                     onChildClick={this.suppressChildClick}
                     docFilters={returnEmptyFilter}
                     docRangeFilters={returnEmptyFilter}
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index ebb953dad..83a49a393 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -67,6 +67,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
             fieldKey: this.props.keyName,
             rootSelected: returnFalse,
             isSelected: returnFalse,
+            setHeight: returnFalse,
             select: emptyFunction,
             dropAction: "alias",
             bringToFront: emptyFunction,
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index ae778f97c..76cf6bbc8 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -680,7 +680,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                 Doc.AddDocToList(Cast(Doc.UserDoc()["template-notes"], Doc, null), "data", this.rootDoc);
             }, icon: "eye"
         });
-        !Doc.UserDoc().noviceMode && appearanceItems.push({ description: "Create progressivized slide...", event: this.progressivizeText, icon: "desktop" });
         cm.addItem({ description: "Appearance...", subitems: appearanceItems, icon: "eye" });
 
         const options = cm.findByDescription("Options...");
@@ -692,66 +691,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         this._downX = this._downY = Number.NaN;
     }
 
-    progressivizeText = () => {
-        const list = this.ProseRef?.getElementsByTagName("li");
-        const mainBulletText: string[] = [];
-        const mainBulletList: Doc[] = [];
-        if (list) {
-            const newBullets: Doc[] = this.recursiveProgressivize(1, list)[0];
-            mainBulletList.push.apply(mainBulletList, newBullets);
-        }
-        const title = Docs.Create.TextDocument(StrCast(this.rootDoc.title), { title: "Title", _width: 800, _height: 70, x: 20, y: -10, _fontSize: '20pt', backgroundColor: "rgba(0,0,0,0)", appearFrame: 0, _fontWeight: 700 });
-        mainBulletList.push(title);
-        const doc = Docs.Create.FreeformDocument(mainBulletList, {
-            title: StrCast(this.rootDoc.title),
-            x: NumCast(this.props.Document.x), y: NumCast(this.props.Document.y) + NumCast(this.props.Document._height) + 10,
-            _width: 400, _height: 225, _fitToBox: true,
-        });
-        this.props.addDocument?.(doc);
-    }
-
-    recursiveProgressivize = (nestDepth: number, list: HTMLCollectionOf<HTMLLIElement>, d?: number, y?: number, before?: string): [Doc[], number] => {
-        const mainBulletList: Doc[] = [];
-        let b = d ? d : 0;
-        let yLoc = y ? y : 0;
-        let nestCount = 0;
-        let count: string = before ? before : '';
-        const fontSize: string = (16 - (nestDepth * 2)) + 'pt';
-        const xLoc: number = (nestDepth * 20);
-        const width: number = 390 - xLoc;
-        const height: number = 55 - (nestDepth * 5);
-        Array.from(list).forEach(listItem => {
-            const mainBullets: number = Number(listItem.getAttribute("data-bulletstyle"));
-            if (mainBullets === nestDepth) {
-                if (listItem.childElementCount > 1) {
-                    b++;
-                    nestCount++;
-                    yLoc += height;
-                    count = before ? count + nestCount + "." : nestCount + ".";
-                    const text = listItem.getElementsByTagName("p")[0].innerText;
-                    const length = text.length;
-                    const bullet1 = Docs.Create.TextDocument(count + " " + text, { title: "Slide text", _width: width, _autoHeight: true, x: xLoc, y: (yLoc), _fontSize: fontSize, backgroundColor: "rgba(0,0,0,0)", appearFrame: d ? d : b });
-                    // yLoc += NumCast(bullet1._height);
-                    mainBulletList.push(bullet1);
-                    const newList = this.recursiveProgressivize(nestDepth + 1, listItem.getElementsByTagName("li"), b, yLoc, count);
-                    mainBulletList.push.apply(mainBulletList, newList[0]);
-                    yLoc += newList.length * (55 - ((nestDepth + 1) * 5));
-                } else {
-                    b++;
-                    nestCount++;
-                    yLoc += height;
-                    count = before ? count + nestCount + "." : nestCount + ".";
-                    const text = listItem.innerText;
-                    const length = text.length;
-                    const bullet1 = Docs.Create.TextDocument(count + " " + text, { title: "Slide text", _width: width, _autoHeight: true, x: xLoc, y: (yLoc), _fontSize: fontSize, backgroundColor: "rgba(0,0,0,0)", appearFrame: d ? d : b });
-                    // yLoc += NumCast(bullet1._height);
-                    mainBulletList.push(bullet1);
-                }
-            }
-        });
-        return [mainBulletList, yLoc];
-    }
-
     recordDictation = () => {
         DictationManager.Controls.listen({
             interimHandler: this.setDictationContent,
@@ -894,14 +833,24 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         return this.focusSpeed;
     }
 
+    resetNativeHeight = (scrollHeight: number) => {
+        const nh = this.layoutDoc.isTemplateForField ? 0 : NumCast(this.layoutDoc._nativeHeight);
+        this.rootDoc[this.fieldKey + "-height"] = scrollHeight * (this.props.scaling?.() || 1) + this.titleHeight;
+        if (nh) {
+            this.layoutDoc._nativeHeight = scrollHeight;
+        }
+    }
+
     componentDidMount() {
         this.props.setContentView?.(this); // this tells the DocumentView that this AudioBox is the "content" of the document.  this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link.
         this.props.contentsActive?.(this.IsActive);
         this._cachedLinks = DocListCast(this.Document.links);
+        this._disposers.scrollHeight = reaction(() => NumCast(this.rootDoc[this.fieldKey + "-scrollHeight"]),
+            scrollHeight => this.layoutDoc.autoHeight && this.resetNativeHeight(scrollHeight));
         this._disposers.sidebarheight = reaction(
-            () => ({ annoHeight: NumCast(this.rootDoc[this.annotationKey + "-height"]), textHeight: NumCast(this.rootDoc[this.fieldKey + "-height"]) }),
-            ({ annoHeight, textHeight }) => {
-                this.layoutDoc._autoHeight && (this.rootDoc._height = Math.max(annoHeight, textHeight));
+            () => ({ sidebarHeight: NumCast(this.rootDoc[this.SidebarKey + "-height"]), textHeight: NumCast(this.rootDoc[this.fieldKey + "-height"]) }),
+            ({ sidebarHeight, textHeight }) => {
+                this.layoutDoc._autoHeight && this.props.setHeight(Math.max(sidebarHeight, textHeight));
             });
         this._disposers.links = reaction(() => DocListCast(this.Document.links), // if a link is deleted, then remove all hyperlinks that reference it from the text's marks
             newLinks => {
@@ -958,20 +907,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             }
         );
         this._disposers.autoHeight = reaction(
-            () => ({
-                width: NumCast(this.layoutDoc._width),
-                autoHeight: this.layoutDoc?._autoHeight
-            }),
-            ({ width, autoHeight }) => width !== undefined && setTimeout(() => this.tryUpdateHeight(), 0)
-        );
-        this._disposers.height = reaction(
-            () => Cast(this.layoutDoc._height, "number", null),
-            action(height => {
-                this.rootDoc[this.fieldKey + "-height"] = height;
-                if (height !== undefined && height <= 20 && height < NumCast(this.layoutDoc._delayAutoHeight, 20)) {
-                    this.layoutDoc._delayAutoHeight = height;
-                }
-            })
+            () => ({ width: NumCast(this.layoutDoc._width), autoHeight: this.layoutDoc?._autoHeight }),
+            ({ width, autoHeight }) => width && autoHeight && this.resetNativeHeight(NumCast(this.layoutDoc[this.fieldKey + "-scrollHeight"]))
         );
 
         this.setupEditor(this.config, this.props.fieldKey);
@@ -1599,28 +1536,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
 
     get titleHeight() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin) || 0; }
 
-    @action
     tryUpdateHeight() {
-        let scrollHeight = Math.min(NumCast(this.layoutDoc.docMaxHeight, 10000), (this.ProseRef?.scrollHeight || 0) * NumCast(this.layoutDoc._viewScale, 1));
-        if (this.props.renderDepth && this.layoutDoc._autoHeight && !this.props.ignoreAutoHeight && scrollHeight && !this.props.dontRegisterView) {  // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation
-            const nh = this.layoutDoc.isTemplateForField ? 0 : NumCast(this.layoutDoc._nativeHeight);
-            const dh = NumCast(this.rootDoc._height);
-            const newHeight = Math.max(10, (nh ? dh / nh * scrollHeight : scrollHeight) + this.titleHeight);
-            if (this.rootDoc !== this.layoutDoc.doc && !this.layoutDoc.resolvedDataDoc) {
-                // if we have a template that hasn't been resolved yet, we can't set the height or we'd be setting it on the unresolved template.  So set a timeout and hope its arrived...
-                console.log("Delayed height adjustment...");
-                setTimeout(() => {
-                    this.rootDoc[this.fieldKey + "-height"] = this.rootDoc._height = newHeight;
-                    this.layoutDoc._nativeHeight = nh ? scrollHeight : undefined;
-                }, 10);
-            } else {
-                try {
-                    const boxHeight = Number(getComputedStyle(this._boxRef.current!).height.replace("px", "")) * NumCast(this.Document._viewScale, 1);
-                    const outer = this.rootDoc[HeightSym]() - boxHeight - this.titleHeight;
-                    this.rootDoc[this.fieldKey + "-height"] = newHeight + Math.max(0, outer);
-                } catch (e) { console.log("Error in tryUpdateHeight"); }
-            }
-        } //else this.rootDoc[this.fieldKey + "-height"] = 0;
+        const proseHeight = this.ProseRef?.scrollHeight || 0;
+        const scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.docMaxAutoHeight, proseHeight), proseHeight);
+        if (scrollHeight && this.props.renderDepth && this.layoutDoc._autoHeight && !this.props.ignoreAutoHeight && !this.props.dontRegisterView) {  // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation
+            if (this.rootDoc === this.layoutDoc.doc || this.layoutDoc.resolvedDataDoc) {
+                this.rootDoc[this.fieldKey + "-scrollHeight"] = scrollHeight;
+            } else setTimeout(() => this.rootDoc[this.fieldKey + "-scrollHeight"] = scrollHeight, 10); // if we have a template that hasn't been resolved yet,   we can't set the height or we'd be setting it on the unresolved template.  So set a timeout and hope its arrived...
+        }
     }
 
     @computed get audioHandle() {
@@ -1644,39 +1567,40 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     sidebarAddDocument = (doc: Doc | Doc[]) => this.addDocument(doc, this.SidebarKey);
     sidebarMoveDocument = (doc: Doc | Doc[], targetCollection: Doc, addDocument: (doc: Doc | Doc[]) => boolean) => this.moveDocument(doc, targetCollection, addDocument, this.SidebarKey);
     sidebarRemDocument = (doc: Doc | Doc[]) => this.removeDocument(doc, this.SidebarKey);
+    setSidebarHeight = (height: number) => this.rootDoc[this.SidebarKey + "-height"] = height;
     @computed get sidebarCollection() {
-        const collectionProps: SubCollectionViewProps & collectionFreeformViewProps = {
-            ...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit,
-            NativeWidth: returnZero,
-            NativeHeight: returnZero,
-            PanelHeight: this.props.PanelHeight,
-            PanelWidth: this.sidebarWidth,
-            xMargin: 0,
-            yMargin: 0,
-            chromeStatus: "enabled",
-            scaleField: this.SidebarKey + "-scale",
-            isAnnotationOverlay: false,
-            fieldKey: this.SidebarKey,
-            fitContentsToDoc: this.fitToBox,
-            select: emptyFunction,
-            active: this.annotationsActive,
-            scaling: this.sidebarContentScaling,
-            whenActiveChanged: this.whenActiveChanged,
-            removeDocument: this.sidebarRemDocument,
-            moveDocument: this.sidebarMoveDocument,
-            addDocument: this.sidebarAddDocument,
-            CollectionView: undefined,
-            ScreenToLocalTransform: this.sidebarScreenToLocal,
-            renderDepth: this.props.renderDepth + 1,
-        };
+        const renderComponent = (tag: string) => {
+            const ComponentTag = tag === "freeform" ? CollectionFreeFormView : tag === "translation" ? FormattedTextBox : CollectionStackingView;
+            return <ComponentTag
+                {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
+                NativeWidth={returnZero}
+                NativeHeight={returnZero}
+                PanelHeight={this.props.PanelHeight}
+                PanelWidth={this.sidebarWidth}
+                xMargin={0}
+                yMargin={0}
+                chromeStatus={"enabled"}
+                scaleField={this.SidebarKey + "-scale"}
+                isAnnotationOverlay={false}
+                setHeight={this.setSidebarHeight}
+                fitContentsToDoc={this.fitToBox}
+                select={emptyFunction}
+                active={this.annotationsActive}
+                scaling={this.sidebarContentScaling}
+                whenActiveChanged={this.whenActiveChanged}
+                removeDocument={this.sidebarRemDocument}
+                moveDocument={this.sidebarMoveDocument}
+                addDocument={this.sidebarAddDocument}
+                CollectionView={undefined}
+                ScreenToLocalTransform={this.sidebarScreenToLocal}
+                renderDepth={this.props.renderDepth + 1}
+                noSidebar={true}
+                fieldKey={this.layoutDoc.sidebarViewType === "translation" ? `${this.fieldKey}-translation` : this.SidebarKey} />
+        }
         return this.props.noSidebar || !this.layoutDoc._showSidebar || this.sidebarWidthPercent === "0%" ? (null) :
             <div className={"formattedTextBox-sidebar" + (Doc.GetSelectedTool() !== InkTool.None ? "-inking" : "")}
                 style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
-                {this.layoutDoc.sidebarViewType === "translation" ?
-                    <FormattedTextBox {...collectionProps} noSidebar={true} fieldKey={`${this.fieldKey}-translation`} /> :
-                    this.layoutDoc.sidebarViewType === CollectionViewType.Freeform ?
-                        <CollectionFreeFormView {...collectionProps} /> :
-                        <CollectionStackingView {...collectionProps} />}
+                {renderComponent(StrCast(this.layoutDoc.sidebarViewType))}
             </div>;
     }
 
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index ca6dc87ae..720d2d92e 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -123,6 +123,12 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
         this.props.startupLive && this.setupPdfJsViewer();
         this._mainCont.current?.addEventListener("scroll", e => (e.target as any).scrollLeft = 0);
 
+        this._disposers.autoHeight = reaction(() => this.layoutDoc._autoHeight,
+            () => {
+                this.layoutDoc._nativeHeight = NumCast(this.props.Document[this.fieldKey + "-nativeHeight"]);
+                this.props.setHeight(NumCast(this.props.Document[this.fieldKey + "-nativeHeight"]) * (this.props.scaling?.() || 1));
+            });
+
         this._disposers.searchMatch = reaction(() => Doc.IsSearchMatch(this.rootDoc),
             m => {
                 if (m) (this._lastSearch = true) && this.search(Doc.SearchQuery(), m.searchMatch > 0);
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 553443931..c82d03fce 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -565,7 +565,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
                                     removeDocument={returnFalse}
                                     PanelHeight={this.open ? this.returnHeight : returnZero}
                                     PanelWidth={this.open ? this.returnLength : returnZero}
-                                    overflow={length > window.innerWidth || this.children > 6 ? true : false}
+                                    scrollOverflow={length > window.innerWidth || this.children > 6 ? true : false}
                                     focus={this.selectElement}
                                     ScreenToLocalTransform={Transform.Identity}
                                 />
-- 
cgit v1.2.3-70-g09d2

