From dbdf81e191107240a62086ebe65d1dc5e3b503c6 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 3 Mar 2020 00:18:36 -0500
Subject: several fixes to templates (simplified expanding, notes use 'text'
 field now, collections show documents when their data field is not a list). 
 multicol/row resizers select their doc.

---
 .../collectionMulticolumn/CollectionMulticolumnView.tsx          | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

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

diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index 82175c0b5..bd20781dc 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -223,17 +223,13 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
      */
     @computed
     private get contents(): JSX.Element[] | null {
-        // bcz: feels like a hack ... trying to show something useful when there's no list document in the data field of a templated object
-        const expanded = Cast(this.props.Document.expandedTemplate, Doc, null);
-        let { childLayoutPairs } = this.dataDoc[this.props.fieldKey] instanceof List || !expanded ? this : { childLayoutPairs: [] } as { childLayoutPairs: { layout: Doc, data: Doc }[] };
-        const replaced = !childLayoutPairs.length && !Cast(expanded?.layout, Doc, null) && expanded;
-        childLayoutPairs = childLayoutPairs.length || !replaced ? childLayoutPairs : [{ layout: replaced, data: replaced }];
+        let { childLayoutPairs } = this;
         const { Document, PanelHeight } = this.props;
         const collector: JSX.Element[] = [];
         for (let i = 0; i < childLayoutPairs.length; i++) {
             const { layout } = childLayoutPairs[i];
             const dxf = () => this.lookupIndividualTransform(layout).translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin));
-            const width = () => expanded ? this.props.PanelWidth() : this.lookupPixels(layout);
+            const width = () => this.lookupPixels(layout);
             const height = () => PanelHeight() - 2 * NumCast(Document._yMargin) - (BoolCast(Document.showWidthLabels) ? 20 : 0);
             collector.push(
                 <div className={"document-wrapper"}
@@ -248,6 +244,7 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
                 <ResizeBar
                     width={resizerWidth}
                     key={"resizer" + i}
+                    select={this.props.select}
                     columnUnitLength={this.getColumnUnitLength}
                     toLeft={layout}
                     toRight={childLayoutPairs[i + 1]?.layout}
-- 
cgit v1.2.3-70-g09d2


From 636e6880a52d3a1a3e24437f47194a902731401d Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Mon, 9 Mar 2020 16:39:42 -0400
Subject: cleanup of warnings

---
 src/client/cognitive_services/CognitiveServices.ts   |  8 ++++----
 src/client/util/DocumentManager.ts                   |  2 +-
 src/client/util/DragManager.ts                       |  2 +-
 src/client/util/ProsemirrorExampleTransfer.ts        |  2 +-
 src/client/util/RichTextSchema.tsx                   | 14 +++++++-------
 src/client/util/SearchUtil.ts                        |  4 ++--
 src/client/views/KeyphraseQueryView.tsx              |  4 ++--
 .../views/collections/CollectionDockingView.tsx      |  4 ++--
 src/client/views/collections/CollectionSubView.tsx   |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx    |  2 +-
 .../CollectionMulticolumnView.tsx                    |  2 +-
 src/client/views/linking/LinkEditor.tsx              |  4 ++--
 src/client/views/nodes/AudioBox.tsx                  |  6 ++----
 src/client/views/nodes/DocuLinkBox.tsx               |  4 ++--
 src/client/views/nodes/DocumentView.tsx              | 14 +++++++-------
 src/client/views/nodes/FormattedTextBox.tsx          | 20 ++++++++------------
 src/client/views/nodes/PDFBox.tsx                    | 10 +++++-----
 17 files changed, 49 insertions(+), 55 deletions(-)

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

diff --git a/src/client/cognitive_services/CognitiveServices.ts b/src/client/cognitive_services/CognitiveServices.ts
index ce829eb1e..542ccf04d 100644
--- a/src/client/cognitive_services/CognitiveServices.ts
+++ b/src/client/cognitive_services/CognitiveServices.ts
@@ -371,9 +371,9 @@ export namespace CognitiveServices {
                 let args = { method: 'POST', uri: Utils.prepend("/recommender"), body: { keyphrases: keyterms }, json: true };
                 await requestPromise.post(args).then(async (wordvecs) => {
                     if (wordvecs) {
-                        let indices = Object.keys(wordvecs);
+                        const indices = Object.keys(wordvecs);
                         console.log("successful vectorization!");
-                        var vectorValues = new List<number>();
+                        const vectorValues = new List<number>();
                         indices.forEach((ind: any) => {
                             //console.log(wordvec.word);
                             vectorValues.push(wordvecs[ind]);
@@ -389,9 +389,9 @@ export namespace CognitiveServices {
             }
 
             export const analyzer = async (dataDoc: Doc, target: Doc, keys: string[], data: string, converter: TextConverter, isMainDoc: boolean = false, isInternal: boolean = true) => {
-                let results = await ExecuteQuery(Service.Text, Manager, data);
+                const results = await ExecuteQuery(Service.Text, Manager, data);
                 console.log("Cognitive Services keyphrases: ", results);
-                let { keyterms, external_recommendations, kp_string } = await converter(results, data);
+                const { keyterms, external_recommendations, kp_string } = await converter(results, data);
                 target[keys[0]] = keyterms;
                 if (isInternal) {
                     //await vectorize([data], dataDoc, isMainDoc);
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 162a8fffe..c41304b9f 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -209,7 +209,7 @@ export class DocumentManager {
             const maxLocation = StrCast(linkDoc.maximizeLocation, "inTab");
             const targetContext = !Doc.AreProtosEqual(linkFollowDocContexts[reverse ? 1 : 0], currentContext) ? linkFollowDocContexts[reverse ? 1 : 0] : undefined;
             const target = linkFollowDocs[reverse ? 1 : 0];
-            let annotatedDoc = await Cast(target.annotationOn, Doc);
+            const annotatedDoc = await Cast(target.annotationOn, Doc);
             if (annotatedDoc) {
                 annotatedDoc.currentTimecode !== undefined && (target.currentTimecode = linkFollowTimecodes[reverse ? 1 : 0]);
             } else {
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index dab5c842c..c11675894 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -198,7 +198,7 @@ export namespace DragManager {
             dropDoc && !dropDoc.creationDate && (dropDoc.creationDate = new DateField);
             dropDoc instanceof Doc && AudioBox.ActiveRecordings.map(d => DocUtils.MakeLink({ doc: dropDoc }, { doc: d }, "audio link", "audio timeline"));
             return dropDoc;
-        }
+        };
         const finishDrag = (e: DragCompleteEvent) => {
             e.docDragData && (e.docDragData.droppedDocuments =
                 dragData.draggedDocuments.map(d => !dragData.isSelectionMove && !dragData.userDropAction && ScriptCast(d.onDragStart) ? addAudioTag(ScriptCast(d.onDragStart).script.run({ this: d }).result) :
diff --git a/src/client/util/ProsemirrorExampleTransfer.ts b/src/client/util/ProsemirrorExampleTransfer.ts
index ec5d1e72a..5cbf401d4 100644
--- a/src/client/util/ProsemirrorExampleTransfer.ts
+++ b/src/client/util/ProsemirrorExampleTransfer.ts
@@ -180,7 +180,7 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, props: any
             return true;
         }
         return false;
-    }
+    };
     bind("Alt-Enter", (state: EditorState<S>, dispatch: (tx: Transaction<Schema<any, any>>) => void) => {
         return addTextOnRight(true);
     });
diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index 0adf060ec..31935df3e 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -889,10 +889,10 @@ export class DashFieldView {
             e.stopPropagation();
             const collview = await Doc.addFieldEnumerations(self._textBoxDoc, node.attrs.fieldKey, [{ title: self._fieldSpan.innerText }]);
             collview instanceof Doc && tbox.props.addDocTab(collview, "onRight");
-        }
+        };
         const updateText = (forceMatch: boolean) => {
             self._enumerables.style.display = "none";
-            let newText = self._fieldSpan.innerText.startsWith(":=") || self._fieldSpan.innerText.startsWith("=:=") ? ":=-computed-" : self._fieldSpan.innerText;
+            const newText = self._fieldSpan.innerText.startsWith(":=") || self._fieldSpan.innerText.startsWith("=:=") ? ":=-computed-" : self._fieldSpan.innerText;
 
             // look for a document whose id === the fieldKey being displayed.  If there's a match, then that document
             // holds the different enumerated values for the field in the titles of its collected documents.
@@ -909,12 +909,12 @@ export class DashFieldView {
 
                 // if the text starts with a ':=' then treat it as an expression by making a computed field from its value storing it in the key
                 if (self._fieldSpan.innerText.startsWith(":=") && self._dashDoc) {
-                    self._dashDoc![self._fieldKey] = ComputedField.MakeFunction(self._fieldSpan.innerText.substring(2));
+                    self._dashDoc[self._fieldKey] = ComputedField.MakeFunction(self._fieldSpan.innerText.substring(2));
                 } else if (self._fieldSpan.innerText.startsWith("=:=") && self._dashDoc) {
                     Doc.Layout(tbox.props.Document)[self._fieldKey] = ComputedField.MakeFunction(self._fieldSpan.innerText.substring(3));
                 }
             });
-        }
+        };
 
         this._fieldSpan = document.createElement("div");
         this._fieldSpan.id = Utils.GenerateGuid();
@@ -926,14 +926,14 @@ export class DashFieldView {
         this._fieldSpan.onkeypress = function (e: any) { e.stopPropagation(); };
         this._fieldSpan.onkeyup = function (e: any) { e.stopPropagation(); };
         this._fieldSpan.onmousedown = function (e: any) { e.stopPropagation(); self._enumerables.style.display = "inline-block"; };
-        this._fieldSpan.onblur = function (e: any) { updateText(false); }
+        this._fieldSpan.onblur = function (e: any) { updateText(false); };
 
         const setDashDoc = (doc: Doc) => {
             self._dashDoc = doc;
             if (self._dashDoc && self._options?.length && !self._dashDoc[node.attrs.fieldKey]) {
                 self._dashDoc[node.attrs.fieldKey] = StrCast(self._options[0].title);
             }
-        }
+        };
         this._fieldSpan.onkeydown = function (e: any) {
             e.stopPropagation();
             if ((e.key === "a" && e.ctrlKey) || (e.key === "a" && e.metaKey)) {
@@ -976,7 +976,7 @@ export class DashFieldView {
                 alias._pivotField = self._fieldKey;
                 tbox.props.addDocTab(alias, "onRight");
             }
-        }
+        };
         this._labelSpan.innerHTML = `${node.attrs.fieldKey}: `;
         if (node.attrs.docid) {
             DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && runInAction(() => setDashDoc(dashDoc)));
diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts
index 64874b994..2d9c807dd 100644
--- a/src/client/util/SearchUtil.ts
+++ b/src/client/util/SearchUtil.ts
@@ -121,12 +121,12 @@ export namespace SearchUtil {
 
     export async function GetAllDocs() {
         const query = "*";
-        let response = await rp.get(Utils.prepend('/search'), {
+        const response = await rp.get(Utils.prepend('/search'), {
             qs:
                 { start: 0, rows: 10000, q: query },
 
         });
-        let result: IdSearchResult = JSON.parse(response);
+        const result: IdSearchResult = JSON.parse(response);
         const { ids, numFound, highlighting } = result;
         //console.log(ids.length);
         const docMap = await DocServer.GetRefFields(ids);
diff --git a/src/client/views/KeyphraseQueryView.tsx b/src/client/views/KeyphraseQueryView.tsx
index a9dafc4a4..1dc156968 100644
--- a/src/client/views/KeyphraseQueryView.tsx
+++ b/src/client/views/KeyphraseQueryView.tsx
@@ -15,8 +15,8 @@ export class KeyphraseQueryView extends React.Component<KP_Props>{
     }
 
     render() {
-        let kps = this.props.keyphrases.toString();
-        let keyterms = this.props.keyphrases.split(',');
+        const kps = this.props.keyphrases.toString();
+        const keyterms = this.props.keyphrases.split(',');
         return (
             <div>
                 <h5>Select queries to send:</h5>
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index db8f7d5e4..00e22d6fb 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -138,8 +138,8 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                 }
             }
             return false;
-        }
-        let retVal = !instance?._goldenLayout.root.contentItems[0].isRow ? false :
+        };
+        const retVal = !instance?._goldenLayout.root.contentItems[0].isRow ? false :
             Array.from(instance._goldenLayout.root.contentItems[0].contentItems).some((child: any) => Array.from(child.contentItems).some(tryClose));
 
         retVal && instance.stateChanged();
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 527623ad4..b995fc7d5 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -107,7 +107,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
         get childLayoutPairs(): { layout: Doc; data: Doc; }[] {
             const { Document, DataDoc } = this.props;
             const validPairs = this.childDocs.map(doc => Doc.GetLayoutDataDocPair(Document, !this.props.annotationsKey ? DataDoc : undefined, doc)).filter(pair => pair.layout);
-            return validPairs.map(({ data, layout }) => ({ data: data!, layout: layout! })); // this mapping is a bit of a hack to coerce types
+            return validPairs.map(({ data, layout }) => ({ data, layout: layout! })); // this mapping is a bit of a hack to coerce types
         }
         get childDocList() {
             return Cast(this.dataField, listSpec(Doc));
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 28f8bc048..7adafea0e 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -801,7 +801,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                 this.props.Document.scrollY = NumCast(doc.y) - offset;
             }
 
-            afterFocus && setTimeout(() => afterFocus?.(), 1000);
+            afterFocus && setTimeout(afterFocus, 1000);
         } else {
             const layoutdoc = Doc.Layout(doc);
             const newPanX = NumCast(doc.x) + NumCast(layoutdoc._width) / 2;
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index bd20781dc..aa8e1fb43 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -223,7 +223,7 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
      */
     @computed
     private get contents(): JSX.Element[] | null {
-        let { childLayoutPairs } = this;
+        const { childLayoutPairs } = this;
         const { Document, PanelHeight } = this.props;
         const collector: JSX.Element[] = [];
         for (let i = 0; i < childLayoutPairs.length; i++) {
diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx
index ac4f8a3cf..b7f3dd995 100644
--- a/src/client/views/linking/LinkEditor.tsx
+++ b/src/client/views/linking/LinkEditor.tsx
@@ -253,8 +253,8 @@ export class LinkGroupEditor extends React.Component<LinkGroupEditorProps> {
     render() {
         const groupType = StrCast(this.props.groupDoc.linkRelationship);
         // if ((groupType && LinkManager.Instance.getMetadataKeysInGroup(groupType).length > 0) || groupType === "") {
-        let buttons = <button className="linkEditor-button" disabled={groupType === ""} onClick={() => this.deleteGroup(groupType)} title="Delete Relationship from all links"><FontAwesomeIcon icon="trash" size="sm" /></button>;
-        let addButton = <button className="linkEditor-addbutton" onClick={() => this.addMetadata(groupType)} disabled={groupType === ""} title="Add metadata to relationship"><FontAwesomeIcon icon="plus" size="sm" /></button>;
+        const buttons = <button className="linkEditor-button" disabled={groupType === ""} onClick={() => this.deleteGroup(groupType)} title="Delete Relationship from all links"><FontAwesomeIcon icon="trash" size="sm" /></button>;
+        const addButton = <button className="linkEditor-addbutton" onClick={() => this.addMetadata(groupType)} disabled={groupType === ""} title="Add metadata to relationship"><FontAwesomeIcon icon="plus" size="sm" /></button>;
 
         return (
             <div className="linkEditor-group">
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 3c8b1c3b8..47883db4e 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -50,7 +50,6 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume
     _recordStart = 0;
     _stream: MediaStream | undefined;
 
-    public static START = 0;
     @observable private static _scrubTime = 0;
     @computed get audioState(): undefined | "recording" | "paused" | "playing" { return this.dataDoc.audioState as (undefined | "recording" | "paused" | "playing"); }
     set audioState(value) { this.dataDoc.audioState = value; }
@@ -146,8 +145,7 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume
         }).then(function (stream) {
             self._stream = stream;
             self._recorder = new MediaRecorder(stream);
-            self.dataDoc[self.props.fieldKey + "-recordingStart"] = new DateField(new Date());
-            AudioBox.START = new DateField(new Date()).date.getTime();
+            self.dataDoc[self.props.fieldKey + "-recordingStart"] = new DateField(new Date()); \
             AudioBox.ActiveRecordings.push(self.props.Document);
             self._recorder.ondataavailable = async function (e: any) {
                 const formData = new FormData();
@@ -208,7 +206,7 @@ export class AudioBox extends DocExtendableComponent<FieldViewProps, AudioDocume
             _width: NumCast(this.props.Document._width), _height: 3 * NumCast(this.props.Document._height)
         });
         Doc.GetProto(newDoc).recordingSource = this.dataDoc;
-        Doc.GetProto(newDoc).recordingStart = 0;
+        Doc.GetProto(newDoc).recordingStart = ComputedField.MakeFunction(`this.recordingSource[${this.props.fieldKey}+"-recordingStart"]`);
         Doc.GetProto(newDoc).audioState = ComputedField.MakeFunction("this.recordingSource.audioState");
         this.props.addDocument?.(newDoc);
         e.stopPropagation();
diff --git a/src/client/views/nodes/DocuLinkBox.tsx b/src/client/views/nodes/DocuLinkBox.tsx
index a0f5b3152..bc663d084 100644
--- a/src/client/views/nodes/DocuLinkBox.tsx
+++ b/src/client/views/nodes/DocuLinkBox.tsx
@@ -113,7 +113,7 @@ export class DocuLinkBox extends DocComponent<FieldViewProps, DocLinkSchema>(Doc
     openLinkEditor = action((e: React.MouseEvent) => {
         SelectionManager.DeselectAll();
         this._editing = this._forceOpen = true;
-    })
+    });
 
     specificContextMenu = (e: React.MouseEvent): void => {
         const funcs: ContextMenuProps[] = [];
@@ -135,7 +135,7 @@ export class DocuLinkBox extends DocComponent<FieldViewProps, DocLinkSchema>(Doc
         const targetTitle = StrCast((this.props.Document[anchor]! as Doc).title) + (timecode !== undefined ? ":" + timecode : "");
         const flyout = (
             <div className="docuLinkBox-flyout" title=" " onPointerOver={() => Doc.UnBrushDoc(this.props.Document)}>
-                <LinkEditor sourceDoc={Cast(this.props.Document[this.props.fieldKey], Doc, null)!} hideback={true} linkDoc={this.props.Document} showLinks={action(() => { })} />
+                <LinkEditor sourceDoc={Cast(this.props.Document[this.props.fieldKey], Doc, null)} hideback={true} linkDoc={this.props.Document} showLinks={action(() => { })} />
                 {!this._forceOpen ? (null) : <div className="docuLinkBox-linkCloser" onPointerDown={action(() => this._isOpen = this._editing = this._forceOpen = false)}>
                     <FontAwesomeIcon color="dimGray" icon={"times"} size={"sm"} />
                 </div>}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 63c6b9f88..a1cba4c2e 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -571,9 +571,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             else if (de.complete.docDragData.draggedDocuments[0].type === "text") {
                 const text = Cast(de.complete.docDragData.draggedDocuments[0].data, RichTextField)?.Text;
                 if (text && text[0] === "{" && text[text.length - 1] === "}" && text.includes(":")) {
-                    let loc = text.indexOf(":");
-                    let key = text.slice(1, loc);
-                    let value = text.slice(loc + 1, text.length - 1);
+                    const loc = text.indexOf(":");
+                    const key = text.slice(1, loc);
+                    const value = text.slice(loc + 1, text.length - 1);
                     console.log(key);
                     console.log(value);
                     console.log(this.props.Document);
@@ -756,7 +756,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             // a.download = `DocExport-${this.props.Document[Id]}.zip`;
             // a.click();
         });
-        let recommender_subitems: ContextMenuProps[] = [];
+        const recommender_subitems: ContextMenuProps[] = [];
 
         recommender_subitems.push({
             description: "Internal recommendations",
@@ -764,7 +764,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             icon: "brain"
         });
 
-        let ext_recommender_subitems: ContextMenuProps[] = [];
+        const ext_recommender_subitems: ContextMenuProps[] = [];
 
         ext_recommender_subitems.push({
             description: "arXiv",
@@ -872,7 +872,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             }
         }));
         const doclist = ClientRecommender.Instance.computeSimilarities("cosine");
-        let recDocs: { preview: Doc, score: number }[] = [];
+        const recDocs: { preview: Doc, score: number }[] = [];
         // tslint:disable-next-line: prefer-for-of
         for (let i = 0; i < doclist.length; i++) {
             recDocs.push({ preview: doclist[i].actualDoc, score: doclist[i].score });
@@ -1113,7 +1113,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             </> :
                 this.innards}
         </div>;
-        { this._showKPQuery ? <KeyphraseQueryView keyphrases={this._queries}></KeyphraseQueryView> : undefined }
+        { this._showKPQuery ? <KeyphraseQueryView keyphrases={this._queries}></KeyphraseQueryView> : undefined; }
     }
 }
 
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 7f5f8538a..1fa603cbd 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -20,7 +20,7 @@ import { InkTool } from '../../../new_fields/InkField';
 import { RichTextField } from "../../../new_fields/RichTextField";
 import { RichTextUtils } from '../../../new_fields/RichTextUtils';
 import { createSchema, makeInterface } from "../../../new_fields/Schema";
-import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
+import { Cast, NumCast, StrCast, BoolCast, DateCast } from "../../../new_fields/Types";
 import { TraceMobx } from '../../../new_fields/util';
 import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, returnOne, Utils, returnTrue } from '../../../Utils';
 import { GoogleApiClientUtils, Pulls, Pushes } from '../../apis/google_docs/GoogleApiClientUtils';
@@ -420,11 +420,11 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
             //this._editorView!.focus();
         });
     }
-    stopDictation = (abort: boolean) => { DictationManager.Controls.stop(!abort); }
+    stopDictation = (abort: boolean) => { DictationManager.Controls.stop(!abort); };
 
     @action
     toggleMenubar = () => {
-        this.props.Document._chromeStatus = this.props.Document._chromeStatus == "disabled" ? "enabled" : "disabled";
+        this.props.Document._chromeStatus = this.props.Document._chromeStatus === "disabled" ? "enabled" : "disabled";
     }
 
     recordBullet = async () => {
@@ -444,12 +444,8 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
 
     setCurrentBulletContent = (value: string) => {
         if (this._editorView) {
-            let state = this._editorView.state;
-            let now = Date.now();
-            if (NumCast(this.props.Document.recordingStart, -1) === 0) {
-                this.props.Document.recordingStart = now = AudioBox.START;
-            }
-            console.log("NOW = " + (now - AudioBox.START) / 1000);
+            const state = this._editorView.state;
+            const now = Date.now();
             let mark = schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(now / 1000) });
             if (!this._break && state.selection.to !== state.selection.from) {
                 for (let i = state.selection.from; i <= state.selection.to; i++) {
@@ -461,9 +457,9 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
                     }
                 }
             }
+            const recordingStart = DateCast(this.props.Document.recordingStart).date.getTime();
             this._break = false;
-            console.log("start = " + (mark.attrs.modified * 1000 - AudioBox.START) / 1000);
-            value = "" + (mark.attrs.modified * 1000 - AudioBox.START) / 1000 + value;
+            value = "" + (mark.attrs.modified * 1000 - recordingStart) / 1000 + value;
             const from = state.selection.from;
             const inserted = state.tr.insertText(value).addMark(from, from + value.length + 1, mark);
             this._editorView.dispatch(inserted.setSelection(TextSelection.create(inserted.doc, from, from + value.length + 1)));
@@ -867,7 +863,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
         if (this._recording && !e.ctrlKey && e.button === 0) {
             this.stopDictation(true);
             this._break = true;
-            let state = this._editorView!.state;
+            const state = this._editorView!.state;
             const to = state.selection.to;
             const updated = TextSelection.create(state.doc, to, to);
             this._editorView!.dispatch(this._editorView!.state.tr.setSelection(updated).insertText("\n", to));
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index f47620c24..4076128b2 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -94,11 +94,11 @@ export class PDFBox extends DocAnnotatableComponent<FieldViewProps, PdfDocument>
         !this.Document._fitWidth && (this.Document._height = this.Document[WidthSym]() * (nh / nw));
     }
 
-    public search = (string: string, fwd: boolean) => { this._pdfViewer?.search(string, fwd); }
-    public prevAnnotation = () => { this._pdfViewer?.prevAnnotation(); }
-    public nextAnnotation = () => { this._pdfViewer?.nextAnnotation(); }
-    public backPage = () => { this._pdfViewer!.gotoPage((this.Document.curPage || 1) - 1); }
-    public forwardPage = () => { this._pdfViewer!.gotoPage((this.Document.curPage || 1) + 1); }
+    public search = (string: string, fwd: boolean) => { this._pdfViewer?.search(string, fwd); };
+    public prevAnnotation = () => { this._pdfViewer?.prevAnnotation(); };
+    public nextAnnotation = () => { this._pdfViewer?.nextAnnotation(); };
+    public backPage = () => { this._pdfViewer!.gotoPage((this.Document.curPage || 1) - 1); };
+    public forwardPage = () => { this._pdfViewer!.gotoPage((this.Document.curPage || 1) + 1); };
     public gotoPage = (p: number) => { this._pdfViewer!.gotoPage(p); };
 
     @undoBatch
-- 
cgit v1.2.3-70-g09d2


From bc23e69a88234c213e444b1aa3c5eb895c35aca9 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Mon, 6 Apr 2020 00:23:19 -0400
Subject: many more fixes to nativewidth/height layout changes.

---
 .../views/collections/CollectionSchemaView.tsx     | 51 ++++++++++++----------
 .../views/collections/CollectionStackingView.tsx   | 14 +++---
 src/client/views/collections/CollectionSubView.tsx |  2 +-
 .../views/collections/CollectionTimeView.tsx       |  2 +-
 .../views/collections/CollectionTreeView.tsx       |  7 +--
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 19 +++++---
 .../CollectionMulticolumnView.tsx                  |  5 +++
 .../CollectionMultirowView.tsx                     |  6 ++-
 .../views/nodes/CollectionFreeFormDocumentView.tsx |  3 +-
 .../views/nodes/ContentFittingDocumentView.tsx     | 17 ++++----
 src/client/views/nodes/DocumentView.tsx            |  4 +-
 src/client/views/nodes/FormattedTextBox.scss       |  9 ++--
 src/client/views/nodes/ImageBox.tsx                |  4 +-
 src/new_fields/util.ts                             |  2 +-
 14 files changed, 82 insertions(+), 63 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index df9f65a21..e835811c9 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -12,7 +12,7 @@ import { List } from "../../../new_fields/List";
 import { listSpec } from "../../../new_fields/Schema";
 import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
 import { ComputedField } from "../../../new_fields/ScriptField";
-import { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types";
+import { Cast, FieldValue, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
 import { Docs, DocumentOptions } from "../../documents/Documents";
 import { Gateway } from "../../northstar/manager/Gateway";
 import { CompileScript, Transformer, ts } from "../../util/Scripting";
@@ -118,29 +118,32 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
 
     @computed
     get previewPanel() {
-        return !this.previewDocument ? (null) : <div ref={this.createTarget} style={{ width: `${this.previewWidth()}px` }}>
-            <ContentFittingDocumentView
-                Document={this.previewDocument}
-                DataDocument={undefined}
-                NativeHeight={returnZero}
-                NativeWidth={returnZero}
-                focus={emptyFunction}
-                LibraryPath={this.props.LibraryPath}
-                renderDepth={this.props.renderDepth}
-                rootSelected={this.rootSelected}
-                PanelWidth={this.previewWidth}
-                PanelHeight={this.previewHeight}
-                getTransform={this.getPreviewTransform}
-                CollectionDoc={this.props.CollectionView && this.props.CollectionView.props.Document}
-                CollectionView={this.props.CollectionView}
-                moveDocument={this.props.moveDocument}
-                addDocument={this.props.addDocument}
-                removeDocument={this.props.removeDocument}
-                active={this.props.active}
-                whenActiveChanged={this.props.whenActiveChanged}
-                addDocTab={this.props.addDocTab}
-                pinToPres={this.props.pinToPres}
-            />
+        return <div ref={this.createTarget} style={{ width: `${this.previewWidth()}px` }}>
+            {!this.previewDocument ? (null) :
+                <ContentFittingDocumentView
+                    Document={this.previewDocument}
+                    DataDocument={undefined}
+                    NativeHeight={returnZero}
+                    NativeWidth={returnZero}
+                    fitToBox={true}
+                    FreezeDimensions={true}
+                    focus={emptyFunction}
+                    LibraryPath={this.props.LibraryPath}
+                    renderDepth={this.props.renderDepth}
+                    rootSelected={this.rootSelected}
+                    PanelWidth={this.previewWidth}
+                    PanelHeight={this.previewHeight}
+                    getTransform={this.getPreviewTransform}
+                    CollectionDoc={this.props.CollectionView?.props.Document}
+                    CollectionView={this.props.CollectionView}
+                    moveDocument={this.props.moveDocument}
+                    addDocument={this.props.addDocument}
+                    removeDocument={this.props.removeDocument}
+                    active={this.props.active}
+                    whenActiveChanged={this.props.whenActiveChanged}
+                    addDocTab={this.props.addDocTab}
+                    pinToPres={this.props.pinToPres}
+                />}
         </div>;
     }
 
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 8ceeb66f1..d17b1ee48 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -116,7 +116,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     componentDidMount() {
         super.componentDidMount();
         this._heightDisposer = reaction(() => {
-            if (this.props.Document._autoHeight && !this.props.NativeHeight()) {
+            if (this.props.Document._autoHeight && !this.layoutDoc._nativeHeight) {
                 const sectionsList = Array.from(this.Sections.size ? this.Sections.values() : [this.filteredChildren]);
                 if (this.isStackingView) {
                     const res = this.props.ContentScaling() * sectionsList.reduce((maxHght, s) => {
@@ -175,17 +175,19 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             backgroundColor={this.props.backgroundColor}
             LayoutDoc={this.props.childLayoutTemplate}
             LibraryPath={this.props.LibraryPath}
-            FreezeDimensions={this.props.freezeDimensions}
+            FreezeDimensions={this.props.freezeChildDimensions}
             renderDepth={this.props.renderDepth + 1}
-            fitToBox={this.props.fitToBox}
+            PanelWidth={width}
+            PanelHeight={height}
+            NativeHeight={returnZero}
+            NativeWidth={returnZero}
+            fitToBox={BoolCast(this.props.Document._freezeChildDimensions)}
             rootSelected={this.rootSelected}
             dropAction={StrCast(this.props.Document.childDropAction) as dropActionType}
             onClick={layoutDoc.isTemplateDoc ? this.onClickHandler : this.onChildClickHandler}
-            PanelWidth={width}
-            PanelHeight={height}
             ScreenToLocalTransform={dxf}
             focus={this.props.focus}
-            ContainingCollectionDoc={this.props.CollectionView && this.props.CollectionView.props.Document}
+            ContainingCollectionDoc={this.props.CollectionView?.props.Document}
             ContainingCollectionView={this.props.CollectionView}
             addDocument={this.props.addDocument}
             moveDocument={this.props.moveDocument}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 32449de5e..a46bc67a2 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -43,7 +43,7 @@ export interface CollectionViewProps extends FieldViewProps {
 export interface SubCollectionViewProps extends CollectionViewProps {
     CollectionView: Opt<CollectionView>;
     children?: never | (() => JSX.Element[]) | React.ReactNode;
-    freezeDimensions?: boolean; // used by TimeView to coerce documents to treat their width height as their native width/height
+    freezeChildDimensions?: boolean; // used by TimeView to coerce documents to treat their width height as their native width/height
     overrideDocuments?: Doc[]; // used to override the documents shown by the sub collection to an explicit list (see LinkBox)
     ignoreFields?: string[]; // used in TreeView to ignore specified fields (see LinkBox)
     isAnnotationOverlay?: boolean;
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index d9a10cdc8..4b005ba42 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -72,7 +72,7 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) {
 
     @computed get contents() {
         return <div className="collectionTimeView-innards" key="timeline" style={{ width: "100%" }}>
-            <CollectionFreeFormView {...this.props} freezeDimensions={BoolCast(this.layoutDoc._freezeChildDimensions, true)} layoutEngine={this.layoutEngine} />
+            <CollectionFreeFormView {...this.props} freezeChildDimensions={BoolCast(this.layoutDoc._freezeChildDimensions, true)} layoutEngine={this.layoutEngine} />
         </div>;
     }
 
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 10da50e35..eff4758cf 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -103,7 +103,7 @@ class TreeView extends React.Component<TreeViewProps> {
     set treeViewOpen(c: boolean) { if (this.props.treeViewPreventOpen) this._overrideTreeViewOpen = c; else this.props.document.treeViewOpen = this._overrideTreeViewOpen = c; }
     @computed get treeViewOpen() { return (!this.props.treeViewPreventOpen && BoolCast(this.props.document.treeViewOpen)) || this._overrideTreeViewOpen; }
     @computed get treeViewExpandedView() { return StrCast(this.props.document.treeViewExpandedView, this.defaultExpandedView); }
-    @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.document.maxEmbedHeight, 300); }
+    @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.containingCollection.maxEmbedHeight, 200); }
     @computed get dataDoc() { return this.templateDataDoc ? this.templateDataDoc : this.props.document; }
     @computed get fieldKey() {
         const splits = StrCast(Doc.LayoutField(this.props.document)).split("fieldKey={\'");
@@ -280,7 +280,7 @@ class TreeView extends React.Component<TreeViewProps> {
     }
     docWidth = () => {
         const layoutDoc = Doc.Layout(this.props.document);
-        const aspect = NumCast(layoutDoc._nativeHeight) / NumCast(layoutDoc._nativeWidth);
+        const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]());
         if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT / aspect, this.props.panelWidth() - 20));
         return NumCast(layoutDoc._nativeWidth) ? Math.min(layoutDoc[WidthSym](), this.props.panelWidth() - 20) : this.props.panelWidth() - 20;
     }
@@ -288,7 +288,7 @@ class TreeView extends React.Component<TreeViewProps> {
         const layoutDoc = Doc.Layout(this.props.document);
         const bounds = this.boundsOfCollectionDocument;
         return Math.min(this.MAX_EMBED_HEIGHT, (() => {
-            const aspect = NumCast(layoutDoc._nativeHeight) / NumCast(layoutDoc._nativeWidth, 1);
+            const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]());
             if (aspect) return this.docWidth() * aspect;
             if (bounds) return this.docWidth() * (bounds.b - bounds.y) / (bounds.r - bounds.x);
             return layoutDoc._fitWidth ? (!this.props.document.nativeHeight ? NumCast(this.props.containingCollection._height) :
@@ -376,6 +376,7 @@ class TreeView extends React.Component<TreeViewProps> {
                     rootSelected={returnTrue}
                     backgroundColor={this.props.backgroundColor}
                     fitToBox={this.boundsOfCollectionDocument !== undefined}
+                    FreezeDimensions={true}
                     PanelWidth={this.docWidth}
                     PanelHeight={this.docHeight}
                     getTransform={this.docTransform}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index ceec9dfcc..22dd2d831 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -15,7 +15,7 @@ import { ScriptField } from "../../../../new_fields/ScriptField";
 import { BoolCast, Cast, FieldValue, NumCast, ScriptCast, StrCast } from "../../../../new_fields/Types";
 import { TraceMobx } from "../../../../new_fields/util";
 import { GestureUtils } from "../../../../pen-gestures/GestureUtils";
-import { aggregateBounds, intersectRect, returnOne, Utils } from "../../../../Utils";
+import { aggregateBounds, intersectRect, returnOne, Utils, returnZero } from "../../../../Utils";
 import { CognitiveServices } from "../../../cognitive_services/CognitiveServices";
 import { DocServer } from "../../../DocServer";
 import { Docs } from "../../../documents/Documents";
@@ -89,7 +89,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     @computed get fitToContent() { return (this.props.fitToBox || this.Document._fitToBox) && !this.isAnnotationOverlay; }
     @computed get parentScaling() { return this.props.ContentScaling && this.fitToContent && !this.isAnnotationOverlay ? this.props.ContentScaling() : 1; }
     @computed get contentBounds() { return aggregateBounds(this._layoutElements.filter(e => e.bounds && !e.bounds.z).map(e => e.bounds!), NumCast(this.layoutDoc.xPadding, 10), NumCast(this.layoutDoc.yPadding, 10)); }
-    @computed get nativeWidth() { return this.Document._fitToContent ? 0 : NumCast(this.Document._nativeWidth, this.props.NativeWidth()); }
+    @computed get nativeWidth() { return this.fitToContent ? 0 : NumCast(this.Document._nativeWidth, this.props.NativeWidth()); }
     @computed get nativeHeight() { return this.fitToContent ? 0 : NumCast(this.Document._nativeHeight, this.props.NativeHeight()); }
     private get isAnnotationOverlay() { return this.props.isAnnotationOverlay; }
     private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; }
@@ -822,10 +822,13 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     getChildDocumentViewProps(childLayout: Doc, childData?: Doc): DocumentViewProps {
         return {
             ...this.props,
+            NativeHeight: returnZero,
+            NativeWidth: returnZero,
+            fitToBox: false,
             DataDoc: childData,
             Document: childLayout,
             LibraryPath: this.libraryPath,
-            FreezeDimensions: this.props.freezeDimensions,
+            FreezeDimensions: this.props.freezeChildDimensions,
             layoutKey: undefined,
             rootSelected: this.rootSelected,
             dropAction: StrCast(this.props.Document.childDropAction) as dropActionType,
@@ -958,8 +961,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                     dataProvider={this.childDataProvider}
                     LayoutDoc={this.childLayoutDocFunc}
                     jitterRotation={NumCast(this.props.Document.jitterRotation)}
-                    fitToBox={this.props.fitToBox || this.props.layoutEngine !== undefined}
-                    FreezeDimensions={this.props.layoutEngine !== undefined}
+                    fitToBox={this.props.fitToBox || BoolCast(this.props.freezeChildDimensions)}
+                    FreezeDimensions={BoolCast(this.props.freezeChildDimensions)}
                 />,
                 bounds: this.childDataProvider(pair.layout)
             }));
@@ -1122,8 +1125,10 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
 
     @computed get contentScaling() {
         if (this.props.annotationsKey) return 0;
-        const hscale = this.nativeHeight ? this.props.PanelHeight() / this.nativeHeight : 1;
-        const wscale = this.nativeWidth ? this.props.PanelWidth() / this.nativeWidth : 1;
+        const nw = NumCast(this.Document._nativeWidth, this.props.NativeWidth());
+        const nh = NumCast(this.Document._nativeHeight, this.props.NativeHeight());
+        const hscale = nh ? this.props.PanelHeight() / nh : 1;
+        const wscale = nw ? this.props.PanelWidth() / nw : 1;
         return wscale < hscale ? wscale : hscale;
     }
     render() {
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index aa8e1fb43..7e511ae34 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -14,6 +14,7 @@ import "./collectionMulticolumnView.scss";
 import ResizeBar from './MulticolumnResizer';
 import WidthLabel from './MulticolumnWidthLabel';
 import { List } from '../../../../new_fields/List';
+import { returnZero } from '../../../../Utils';
 
 type MulticolumnDocument = makeInterface<[typeof documentSchema]>;
 const MulticolumnDocument = makeInterface(documentSchema);
@@ -208,6 +209,10 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
             {...this.props}
             Document={layout}
             DataDocument={layout.resolvedDataDoc as Doc}
+            NativeHeight={returnZero}
+            NativeWidth={returnZero}
+            fitToBox={BoolCast(this.props.Document._freezeChildDimensions)}
+            FreezeDimensions={BoolCast(this.props.Document._freezeChildDimensions)}
             backgroundColor={this.props.backgroundColor}
             CollectionDoc={this.props.Document}
             PanelWidth={width}
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index 5e59f8237..daf1fda6c 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -6,7 +6,7 @@ import * as React from "react";
 import { Doc } from '../../../../new_fields/Doc';
 import { NumCast, StrCast, BoolCast, ScriptCast } from '../../../../new_fields/Types';
 import { ContentFittingDocumentView } from '../../nodes/ContentFittingDocumentView';
-import { Utils } from '../../../../Utils';
+import { Utils, returnZero } from '../../../../Utils';
 import "./collectionMultirowView.scss";
 import { computed, trace, observable, action } from 'mobx';
 import { Transform } from '../../../util/Transform';
@@ -208,6 +208,10 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
             {...this.props}
             Document={layout}
             DataDocument={layout.resolvedDataDoc as Doc}
+            NativeHeight={returnZero}
+            NativeWidth={returnZero}
+            fitToBox={BoolCast(this.props.Document._freezeChildDimensions)}
+            FreezeDimensions={BoolCast(this.props.Document._freezeChildDimensions)}
             backgroundColor={this.props.backgroundColor}
             CollectionDoc={this.props.Document}
             PanelWidth={width}
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index e4c8bbd7b..7e9e654cd 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -10,7 +10,6 @@ import { DocumentView, DocumentViewProps } from "./DocumentView";
 import React = require("react");
 import { PositionDocument } from "../../../new_fields/documentSchemas";
 import { TraceMobx } from "../../../new_fields/util";
-import { returnFalse } from "../../../Utils";
 import { ContentFittingDocumentView } from "./ContentFittingDocumentView";
 
 export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
@@ -108,7 +107,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                     getTransform={this.getTransform}
                     NativeHeight={this.NativeHeight}
                     NativeWidth={this.NativeWidth}
-                    active={returnFalse}
+                    active={this.props.parentActive}
                     focus={this.focusDoc}
                     PanelWidth={this.panelWidth}
                     PanelHeight={this.panelHeight}
diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx
index 52e5ed1dd..f66ff8020 100644
--- a/src/client/views/nodes/ContentFittingDocumentView.tsx
+++ b/src/client/views/nodes/ContentFittingDocumentView.tsx
@@ -2,7 +2,7 @@ import React = require("react");
 import { computed } from "mobx";
 import { observer } from "mobx-react";
 import "react-table/react-table.css";
-import { Doc, Opt } from "../../../new_fields/Doc";
+import { Doc, Opt, WidthSym, HeightSym } from "../../../new_fields/Doc";
 import { ScriptField } from "../../../new_fields/ScriptField";
 import { NumCast, StrCast } from "../../../new_fields/Types";
 import { TraceMobx } from "../../../new_fields/util";
@@ -15,7 +15,7 @@ import "./ContentFittingDocumentView.scss";
 import { dropActionType } from "../../util/DragManager";
 
 interface ContentFittingDocumentViewProps {
-    Document?: Doc;
+    Document: Doc;
     DataDocument?: Doc;
     LayoutDoc?: () => Opt<Doc>;
     NativeWidth?: () => number;
@@ -48,13 +48,14 @@ interface ContentFittingDocumentViewProps {
 @observer
 export class ContentFittingDocumentView extends React.Component<ContentFittingDocumentViewProps>{
     public get displayName() { return "DocumentView(" + this.props.Document?.title + ")"; } // this makes mobx trace() statements more descriptive
-    private get layoutDoc() { return this.props.Document && (this.props.LayoutDoc?.() || Doc.Layout(this.props.Document)); }
-    private nativeWidth = () => NumCast(this.layoutDoc?._nativeWidth, this.props.NativeWidth?.() || this.props.PanelWidth());
-    private nativeHeight = () => NumCast(this.layoutDoc?._nativeHeight, this.props.NativeHeight?.() || this.props.PanelHeight());
+    private get layoutDoc() { return this.props.LayoutDoc?.() || Doc.Layout(this.props.Document); }
+    @computed get freezeDimensions() { return this.props.FreezeDimensions; }
+    nativeWidth = () => { return NumCast(this.layoutDoc?._nativeWidth, this.props.NativeWidth?.() || (this.freezeDimensions && this.layoutDoc ? this.layoutDoc[WidthSym]() : this.props.PanelWidth())); }
+    nativeHeight = () => { return NumCast(this.layoutDoc?._nativeHeight, this.props.NativeHeight?.() || (this.freezeDimensions && this.layoutDoc ? this.layoutDoc[HeightSym]() : this.props.PanelHeight())); }
     @computed get scaling() {
-        const wscale = this.props.PanelWidth() / (this.nativeWidth() || this.props.PanelWidth() || 1);
+        const wscale = this.props.PanelWidth() / this.nativeWidth();
         if (wscale * this.nativeHeight() > this.props.PanelHeight()) {
-            return (this.props.PanelHeight() / (this.nativeHeight() || this.props.PanelHeight() || 1)) || 1;
+            return (this.props.PanelHeight() / this.nativeHeight()) || 1;
         }
         return wscale || 1;
     }
@@ -67,7 +68,7 @@ export class ContentFittingDocumentView extends React.Component<ContentFittingDo
     @computed get panelHeight() { return this.nativeHeight && (!this.props.Document || !this.props.Document._fitWidth) ? this.nativeHeight() * this.contentScaling() : this.props.PanelHeight(); }
 
     private getTransform = () => this.props.getTransform().translate(-this.centeringOffset, -this.centeringYOffset).scale(1 / this.contentScaling());
-    private get centeringOffset() { return this.nativeWidth && (!this.props.Document || !this.props.Document._fitWidth) ? (this.props.PanelWidth() - this.nativeWidth() * this.contentScaling()) / 2 : 0; }
+    private get centeringOffset() { return this.nativeWidth() && !this.props.Document._fitWidth ? (this.props.PanelWidth() - this.nativeWidth() * this.contentScaling()) / 2 : 0; }
     private get centeringYOffset() { return Math.abs(this.centeringOffset) < 0.001 ? (this.props.PanelHeight() - this.nativeHeight() * this.contentScaling()) / 2 : 0; }
 
     @computed get borderRounding() { return StrCast(this.props.Document?.borderRounding); }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index d800579a1..32c5a02e5 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -110,7 +110,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
     public get displayName() { return "DocumentView(" + this.props.Document.title + ")"; } // this makes mobx trace() statements more descriptive
     public get ContentDiv() { return this._mainCont.current; }
-    @computed get active() { return SelectionManager.IsSelected(this, true) || this.props.parentActive(true); }
+    get active() { return SelectionManager.IsSelected(this, true) || this.props.parentActive(true); }
     @computed get topMost() { return this.props.renderDepth === 0; }
     @computed get freezeDimensions() { return this.props.FreezeDimensions; }
     @computed get nativeWidth() { return NumCast(this.layoutDoc._nativeWidth, this.props.NativeWidth() || (this.freezeDimensions ? this.layoutDoc[WidthSym]() : 0)); }
@@ -124,8 +124,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     private _firstX: number = -1;
     private _firstY: number = -1;
 
-
-
     handle1PointerHoldStart = (e: Event, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>): any => {
         this.removeMoveListeners();
         this.removeEndListeners();
diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss
index 526939438..7d40b3149 100644
--- a/src/client/views/nodes/FormattedTextBox.scss
+++ b/src/client/views/nodes/FormattedTextBox.scss
@@ -39,11 +39,6 @@
         position: absolute;
     }
 }
-
-.collectionfreeformview-container {
-    position: relative;
-}
-
 .formattedTextBox-outer {
     position: relative;
     overflow: auto;
@@ -75,6 +70,10 @@
     position: absolute;
     right: 0;
 
+    .collectionfreeformview-container {
+        position: relative;
+    }
+    
     >.formattedTextBox-sidebar-handle {
         right: unset;
         left: -5;
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 052251d94..e0b3a6809 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -433,12 +433,14 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum
     contentFunc = () => [this.content];
     render() {
         TraceMobx();
+        const rotation = NumCast(this.dataDoc[this.fieldKey + "-rotation"]);
+        const aspect = (rotation % 180) ? this.Document[HeightSym]() / this.Document[WidthSym]() : 1;
         const dragging = !SelectionManager.GetIsDragging() ? "" : "-dragging";
         return (<div className={`imageBox${dragging}`} onContextMenu={this.specificContextMenu}
             style={{
                 transform: this.props.PanelWidth() ? undefined : `scale(${this.props.ContentScaling()})`,
                 width: this.props.PanelWidth() ? `${this.props.PanelWidth()}px` : `${100 / this.props.ContentScaling()}%`,
-                height: this.props.PanelWidth() ? undefined : `${100 / this.props.ContentScaling()}%`,
+                height: this.props.PanelWidth() ? `${this.props.PanelWidth() * aspect}px` : `${100 / this.props.ContentScaling()}%`,
                 pointerEvents: this.props.Document.isBackground ? "none" : undefined,
                 borderRadius: `${Number(StrCast(this.layoutDoc.borderRounding).replace("px", "")) / this.props.ContentScaling()}px`
             }} >
diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts
index 480a55da0..8c719ccd8 100644
--- a/src/new_fields/util.ts
+++ b/src/new_fields/util.ts
@@ -12,7 +12,7 @@ function _readOnlySetter(): never {
     throw new Error("Documents can't be modified in read-only mode");
 }
 
-const tracing = true;
+const tracing = false;
 export function TraceMobx() {
     tracing && trace();
 }
-- 
cgit v1.2.3-70-g09d2

