From fd329ad25987122c8f2a31177a6c346c97f00457 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 25 Feb 2021 18:54:45 -0500
Subject: added 'proto' drag option for dropping proto of document.  auto add
 of non annotations to file system.  auto added delegates & aliases to a
 docuemnt's 'alias' field.

---
 src/client/views/LightboxView.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src/client/views/LightboxView.tsx')

diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index babc518ff..e1fbea76e 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -46,7 +46,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
             this._docFilters && (this._docFilters.length = 0);
             this._future = this._history = [];
         } else {
-            TabDocView.PinDoc(doc, { hidePresBox: true });
+            //TabDocView.PinDoc(doc, { hidePresBox: true });
             this._history ? this._history.push({ doc, target }) : this._history = [{ doc, target }];
             if (doc !== LightboxView.LightboxDoc) {
                 this._savedState = {
-- 
cgit v1.2.3-70-g09d2


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/documents/Documents.ts           | 301 +++++++---------------------
 src/client/util/CurrentUserUtils.ts         |   3 +-
 src/client/views/LightboxView.tsx           |   2 +-
 src/client/views/collections/TabDocView.tsx |   3 +-
 src/client/views/collections/TreeView.tsx   |   2 +-
 5 files changed, 77 insertions(+), 234 deletions(-)

(limited to 'src/client/views/LightboxView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index b5b179d3a..de08040e2 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -25,6 +25,7 @@ import { DirectoryImportBox } from "../util/Import & Export/DirectoryImportBox";
 import { LinkManager } from "../util/LinkManager";
 import { Scripting } from "../util/Scripting";
 import { undoBatch, UndoManager } from "../util/UndoManager";
+import { DimUnit } from "../views/collections/collectionMulticolumn/CollectionMulticolumnView";
 import { CollectionDockingView } from "../views/collections/CollectionDockingView";
 import { CollectionView, CollectionViewType } from "../views/collections/CollectionView";
 import { ContextMenu } from "../views/ContextMenu";
@@ -59,205 +60,56 @@ import { DocumentType } from "./DocumentTypes";
 const path = require('path');
 
 const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", ""));
-interface dinfo {
-    description: string;
-    type: string;
-    dflt?: any;
+class EmptyBox {
+    public static LayoutString() {
+        return "";
+    }
 }
-export interface DocumentOptions {
-    system?: boolean | dinfo;
-    _autoHeight?: boolean | dinfo;
-    _headerHeight?: number | dinfo; // height of header of custom notes
-    _headerFontSize?: number | dinfo; // font size of header of custom notes
-    _headerPointerEvents?: string | dinfo; // types of events the header of a custom text document can consume
-    _panX?: number | dinfo;
-    _panY?: number | dinfo;
-    _width?: number | dinfo;
-    _height?: number | dinfo;
-    _nativeWidth?: number | dinfo;
-    _nativeHeight?: number | dinfo;
-    _dimMagnitude?: number | dinfo; // magnitude of collectionMulti{row,col} view element
-    _dimUnit?: string | dinfo; // "px" or "*" (default = "*")
-    _fitWidth?: boolean | dinfo;
-    _fitToBox?: boolean; // whether a freeformview should zoom/scale to create a shrinkwrapped view of its contents
-    _freeformLOD?: boolean; // whether to use LOD to render a freeform document
-    _showTitle?: string; // field name to display in header (:hover is an optional suffix)
-    _showCaption?: string; // which field to display in the caption area.  leave empty to have no caption
-    _scrollTop?: number; // scroll location for pdfs
-    _noAutoscroll?: boolean;// whether collections autoscroll when this item is dragged
-    _chromeStatus?: string;
-    _searchDoc?: boolean; // is this a search document (used to change UI for search results in schema view)
-    _viewType?: string; // sub type of a collection
-    _gridGap?: number; // gap between items in masonry view
-    _xMargin?: number; // gap between left edge of document and start of masonry/stacking layouts
-    _yMargin?: number; // gap between top edge of dcoument and start of masonry/stacking layouts
-    _xPadding?: number;
-    _yPadding?: number;
-    _itemIndex?: number; // which item index the carousel viewer is showing
-    _showSidebar?: boolean;  //whether an annotationsidebar should be displayed for text docuemnts
-    _singleLine?: boolean; // whether text document is restricted to a single line (carriage returns make new document)
-    "_carousel-caption-xMargin"?: number;
-    "_carousel-caption-yMargin"?: number;
-    x?: number;
-    y?: number;
-    z?: number;
-    author?: string;
-    _hideContextMenu?: boolean; // whether the context menu can be shown
-    dropAction?: dropActionType;
-    childDropAction?: dropActionType;
-    targetDropAction?: dropActionType;
-    layoutKey?: string;
+abstract class FInfo {
+    description: string = "";
     type?: string;
-    title?: string;
-    version?: string; // version identifier for a document
-    label?: string;
-    hidden?: boolean;
-    userDoc?: Doc; // the userDocument
-    toolTip?: string; // tooltip to display on hover
-    style?: string;
-    page?: number;
-    dontUndo?: boolean; // whether button clicks should be undoable (this is set to true for Undo/Redo/and sidebar buttons that open the siebar panel)
-    description?: string; // added for links
-    _viewScale?: number;
-    _overflow?: string;
-    forceActive?: boolean;
-    layout?: string | Doc; // default layout string for a document
-    contentPointerEvents?: string;  // pointer events allowed for content of a document view.  eg. set to "none" in menuSidebar for sharedDocs so that you can select a document, but not interact with its contents
-    childLimitHeight?: number; // whether to limit the height of colleciton children.  0 - means  height can be no bigger than width
-    childLayoutTemplate?: Doc; // template for collection to use to render its children (see PresBox or Buxton layout in tree view)
-    childLayoutString?: string; // template string for collection to use to render its children
-    hideLinkButton?: boolean; // whether the blue link counter button should be hidden
-    hideAllLinks?: boolean; // whether all individual blue anchor dots should be hidden
-    _columnsHideIfEmpty?: boolean; // whether stacking view column headings should be hidden
-    isTemplateForField?: string; // the field key for which the containing document is a rendering template
-    isTemplateDoc?: boolean;
-    watchedDocuments?: Doc; // list of documents to "watch" in an icon doc to display a badge
-    targetScriptKey?: string; // where to write a template script (used by collections with click templates which need to target onClick, onDoubleClick, etc)
-    templates?: List<string>;
-    hero?: ImageField; // primary image that best represents a compound document (e.g., for a buxton device document that has multiple images)
-    backgroundColor?: string | ScriptField;  // background color for data doc 
-    _backgroundColor?: string | ScriptField; // background color for each template layout doc ( overrides backgroundColor )
-    color?: string; // foreground color data doc
-    _color?: string;  // foreground color for each template layout doc (overrides color)
-    _clipWidth?: number; // percent transition from before to after in comparisonBox
-    caption?: RichTextField;
-    ignoreClick?: boolean;
-    lockedPosition?: boolean; // lock the x,y coordinates of the document so that it can't be dragged
-    _lockedTransform?: boolean; // lock the panx,pany and scale parameters of the document so that it be panned/zoomed
-    isAnnotating?: boolean; // whether we web document is annotation mode where links can't be clicked to allow annotations to be created
-    opacity?: number;
-    defaultBackgroundColor?: string;
-    _layers?: List<string>;
-    _raiseWhenDragged?: boolean; // whether a document is brought to front when dragged.
-    isLinkButton?: boolean;
-    isFolder?: boolean;
-    _columnWidth?: number;
-    _fontSize?: string;
-    _fontWeight?: number;
-    _fontFamily?: string;
-    _curPage?: number;
-    _currentTimecode?: number; // the current timecode of a time-based document (e.g., current time of a video)  value is in seconds
-    _currentFrame?: number; // the current frame of a frame-based collection (e.g., progressive slide)
-    _timecodeToShow?: number; // the time that a document should be displayed (e.g., when an annotation shows up as a video plays)
-    _timecodeToHide?: number; // the time that a document should be hidden
-    _timelineLabel?: boolean; // whether the document exists on a timeline
-    lastFrame?: number; // the last frame of a frame-based collection (e.g., progressive slide)
-    activeFrame?: number; // the active frame of a document in a frame base collection
-    appearFrame?: number; // the frame in which the document appears
-    presTransition?: number; //the time taken for the transition TO a document
-    presDuration?: number; //the duration of the slide in presentation view
-    presProgressivize?: boolean;
-    borderRounding?: string;
-    boxShadow?: string;
-    dontRegisterChildViews?: boolean;
-    dontRegisterView?: boolean;
-    lookupField?: ScriptField; // script that returns the value of a field. This script is passed the rootDoc, layoutDoc, field, and container of the document.  see PresBox.
-    "onDoubleClick-rawScript"?: string; // onDoubleClick script in raw text form
-    "onChildDoubleClick-rawScript"?: string; // onChildDoubleClick script in raw text form
-    "onChildClick-rawScript"?: string; // on ChildClick script in raw text form
-    "onClick-rawScript"?: string; // onClick script in raw text form
-    "onCheckedClick-rawScript"?: string; // onChecked script in raw text form
-    "onCheckedClick-params"?: List<string>; // parameter list for onChecked treeview functions
-    _pivotField?: string; // field key used to determine headings for sections in stacking, masonry, pivot views
-    _columnHeaders?: List<SchemaHeaderField>; // headers for stacking views
-    _schemaHeaders?: List<SchemaHeaderField>; // headers for schema view
-    dockingConfig?: string;
-    annotationOn?: Doc;
-    isPushpin?: boolean;
-    removeDropProperties?: List<string>; // list of properties that should be removed from a document when it is dropped.  e.g., a creator button may be forceActive to allow it be dragged, but the forceActive property can be removed from the dropped document
-    dbDoc?: Doc;
-    iconShape?: string; // shapes of the fonticon border
-    linkRelationship?: string; // type of relatinoship a link represents
-    ischecked?: ScriptField; // returns whether a font icon box is checked
-    activeInkPen?: Doc; // which pen document is currently active (used as the radio button state for the 'unhecked' pen tool scripts)
-    onClick?: ScriptField;
-    onDoubleClick?: ScriptField;
-    onChildClick?: ScriptField; // script given to children of a collection to execute when they are clicked
-    onChildDoubleClick?: ScriptField; // script given to children of a collection to execute when they are double clicked
-    onPointerDown?: ScriptField;
-    onPointerUp?: ScriptField;
-    dropConverter?: ScriptField; // script to run when documents are dropped on this Document.
-    dragFactory?: Doc; // document to create when dragging with a suitable onDragStart script
-    clickFactory?: Doc; // document to create when clicking on a button with a suitable onClick script
-    onDragStart?: ScriptField; //script to execute at start of drag operation --  e.g., when a "creator" button is dragged this script generates a different document to drop
-    clipboard?: Doc;
-    useCors?: boolean;
-    icon?: string;
-    target?: Doc; // available for use in scripts as the primary target document
-    sourcePanel?: Doc; // panel to display in 'targetContainer' as the result of a button onClick script
-    targetContainer?: Doc; // document whose proto will be set to 'panel' as the result of a onClick click script
-    searchFileTypes?: List<string>; // file types allowed in a search query
-    strokeWidth?: number;
-    cloneFieldFilter?: List<string>; // fields not to copy when the document is cloned
-    _stayInCollection?: boolean;// whether the document should remain in its collection when someone tries to drag and drop it elsewhere
-    freezeChildren?: string; // whether children are now allowed to be added and or removed from a collection
-    treeViewPreventOpen?: boolean; // ignores the treeViewOpen Doc flag which allows a treeViewItem's expand/collapse state to be independent of other views of the same document in the tree view
-    treeViewHideTitle?: boolean; // whether to hide the top document title of a tree view
-    treeViewHideHeader?: boolean; // whether to hide the header for a document in a tree view
-    treeViewHideHeaderFields?: boolean; // whether to hide the drop down options for tree view items.
-    treeViewOpen?: boolean; // whether this document is expanded in a tree view
-    treeViewExpandedView?: string; // which field/thing is displayed when this item is opened in tree view
-    treeViewChecked?: ScriptField; // script to call when a tree view checkbox is checked
-    treeViewTruncateTitleWidth?: number;
-    treeViewType?: string; // whether treeview is a Slide, file system, or (default) collection hierarchy
-    treeViewLockExpandedView?: boolean; // whether the expanded view can be changed
-    treeViewDefaultExpandedView?: string; // default expanded view
-    sidebarColor?: string;  // background color of text sidebar
-    sidebarViewType?: string; // collection type of text sidebar
-    limitHeight?: number; // maximum height for newly created (eg, from pasting) text documents
-    // [key: string]: Opt<Field>;
-    pointerHack?: boolean; // for buttons, allows onClick handler to fire onPointerDown
-    textTransform?: string; // is linear view expanded
-    letterSpacing?: string; // is linear view expanded
-    flexDirection?: "unset" | "row" | "column" | "row-reverse" | "column-reverse";
-    selectedIndex?: number;
-    syntaxColor?: string; // can be applied to text for syntax highlighting all matches in the text
-    searchQuery?: string; // for quersyBox
-    linearViewIsExpanded?: boolean; // is linear view expanded
-    isLabel?: boolean;         // whether the document is a label or not (video / audio)
-    useLinkSmallAnchor?: boolean;  // whether links to this document should use a miniature linkAnchorBox
-    border?: string; //for searchbox
-    _hovercolor?: string;
+    values?: Field[];
+    layoutField?: boolean; // is this field a layout (or datadoc) field
+    // format?: string; // format to display values (e.g, decimal places, $, etc)
+    // parse?: ScriptField; // parse a value from a string
+    constructor(d: string, l: boolean = false) { this.description = d; this.layoutField = l; }
 }
-
-let _docOptions: DocumentOptions = {
-    system: { type: "string", description: "is document created/owned by the system", dflt: false },
-    _autoHeight: { type: "boolean", description: "whether document automatically resizes vertically to display contents", dflt: false },
-    _headerHeight: { type: "number", description: "height of document header used for displaying title", dflt: 20 },
-    _headerFontSize: { type: "number", description: "font size of header of custom notes", dflt: 12 },
-    _headerPointerEvents: { type: "string", description: "types of events the header of a custom text document can consume" },
-    _panX: { type: "number", description: "horizontal pan location of a freeform view" },
-    _panY: { type: "number", description: "vertical pan location of a freeform view" },
-    _width: { type: "number", description: "displayed width of a document" },
-    _height: { type: "number", description: "displayed height of document" },
-    _nativeWidth: { type: "number", description: "native width of document contents (e.g., the pixel width of an image)" },
-    _nativeHeight: { type: "number", description: "native height of document contents (e.g., the pixel height of an image)" },
-    _dimMagnitude: { type: "number", description: "magnitude of collectionMulti{row,col} element's width or height" },
-    _dimUnit: { type: "string", description: "units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units" },
-    _fitWidth: { type: "boolean", description: "whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)" }
-
-}
-/*_fitToBox?: boolean; // whether a freeformview should zoom/scale to create a shrinkwrapped view of its contents
+class BoolInfo extends FInfo { type?= "boolean"; values?: boolean[] = [true, false]; }
+class NumInfo extends FInfo { type?= "number"; values?: number[] = []; }
+class StrInfo extends FInfo { type?= "string"; values?: string[] = []; }
+class DocInfo extends FInfo { type?= "Doc"; values?: Doc[] = []; }
+class DimInfo extends FInfo { type?= "DimUnit"; values?= [DimUnit.Pixel, DimUnit.Ratio]; }
+class PEInfo extends FInfo { type?= "pointerEvents"; values?= ["all", "none"]; }
+class DAInfo extends FInfo { type?= "dropActionType"; values?= ["alias", "copy", "move", "same", "proto", "none"]; }
+type BOOLt = BoolInfo | boolean;
+type NUMt = NumInfo | number;
+type STRt = StrInfo | string;
+type DOCt = DocInfo | Doc;
+type DIMt = DimInfo | typeof DimUnit.Pixel | typeof DimUnit.Ratio;
+type PEVt = PEInfo | "none" | "all";
+type DROPt = DAInfo | dropActionType;
+export class DocumentOptions {
+    system?: BOOLt = new BoolInfo("is this a system created/owned doc");
+    userDoc?: DOCt = new DocInfo("the user doc");
+    dropAction?: DROPt = new DAInfo("what should happen to the source document when it's dropped onto this doc ");
+    childDropAction?: DROPt = new DAInfo("what should happen to the source document when it's dropped onto a child of a collection ");
+    targetDropAction?: DROPt = new DAInfo("what should happen to the source document when ??? ");
+    backgroundColor?: STRt = new StrInfo("background color for data doc");
+    _backgroundColor?: STRt = new StrInfo("background color for each template layout doc (overrides backgroundColor)", true);
+    _autoHeight?: BOOLt = new BoolInfo("whether document automatically resizes vertically to display contents", true);
+    _headerHeight?: NUMt = new NumInfo("height of document header used for displaying title", true);
+    _headerFontSize?: NUMt = new NumInfo("font size of header of custom notes", true);
+    _headerPointerEvents?: PEVt = new PEInfo("types of events the header of a custom text document can consume", true);
+    _panX?: NUMt = new NumInfo("horizontal pan location of a freeform view", true);
+    _panY?: NUMt = new NumInfo("vertical pan location of a freeform view", true);
+    _width?: NUMt = new NumInfo("displayed width of a document", true);
+    _height?: NUMt = new NumInfo("displayed height of document", true);
+    _nativeWidth?: NUMt = new NumInfo("native width of document contents (e.g., the pixel width of an image)", true);
+    _nativeHeight?: NUMt = new NumInfo("native height of document contents (e.g., the pixel height of an image)", true);
+    _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height", true);
+    _dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units", true);
+    _fitWidth?: BOOLt = new BoolInfo("whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)", true);
+    _fitToBox?: boolean; // whether a freeformview should zoom/scale to create a shrinkwrapped view of its contents
     _freeformLOD?: boolean; // whether to use LOD to render a freeform document
     _showTitle?: string; // field name to display in header (:hover is an optional suffix)
     _showCaption?: string; // which field to display in the caption area.  leave empty to have no caption
@@ -281,16 +133,12 @@ let _docOptions: DocumentOptions = {
     z?: number;
     author?: string;
     _hideContextMenu?: boolean; // whether the context menu can be shown
-    dropAction?: dropActionType;
-    childDropAction?: dropActionType;
-    targetDropAction?: dropActionType;
     layoutKey?: string;
     type?: string;
     title?: string;
     version?: string; // version identifier for a document
     label?: string;
     hidden?: boolean;
-    userDoc?: Doc; // the userDocument
     toolTip?: string; // tooltip to display on hover
     style?: string;
     page?: number;
@@ -313,8 +161,6 @@ let _docOptions: DocumentOptions = {
     targetScriptKey?: string; // where to write a template script (used by collections with click templates which need to target onClick, onDoubleClick, etc)
     templates?: List<string>;
     hero?: ImageField; // primary image that best represents a compound document (e.g., for a buxton device document that has multiple images)
-    backgroundColor?: string | ScriptField;  // background color for data doc 
-    _backgroundColor?: string | ScriptField; // background color for each template layout doc ( overrides backgroundColor )
     color?: string; // foreground color data doc
     _color?: string;  // foreground color for each template layout doc (overrides color)
     _clipWidth?: number; // percent transition from before to after in comparisonBox
@@ -416,37 +262,34 @@ let _docOptions: DocumentOptions = {
     useLinkSmallAnchor?: boolean;  // whether links to this document should use a miniature linkAnchorBox
     border?: string; //for searchbox
     _hovercolor?: string;
-}*/
-
-class EmptyBox {
-    public static LayoutString() {
-        return "";
-    }
 }
-
 export namespace Docs {
 
-    export let FieldInfos: Doc | undefined;
+    const _docOptions = new DocumentOptions();
+
     export async function setupFieldInfos() {
-        const fieldDocs = await DocServer.GetRefField("FieldInfos");
-        if (fieldDocs instanceof Doc) {
-            Docs.FieldInfos = fieldDocs;
-        } else {
+        return await DocServer.GetRefField("FieldInfos7") as Doc ??
             runInAction(() => {
-                const infos = Docs.FieldInfos = new Doc("FieldInfos", true);
-                const keys = Object.keys(_docOptions);
-                for (let i = 0; i < keys.length; i++) {
-                    const key = keys[i];
-                    const options = (_docOptions as any)[key] as dinfo;
+                const infos = new Doc("FieldInfos7", true);
+                const keys = Object.keys(new DocumentOptions());
+                for (const key of keys) {
+                    const options = (_docOptions as any)[key] as FInfo;
                     const finfo = new Doc();
                     finfo.name = key;
-                    finfo.default = options.dflt;
+                    switch (options.type) {
+                        case "boolean": finfo.options = new List<boolean>(options.values as any as boolean[]); break;
+                        case "number": finfo.options = new List<number>(options.values as any as number[]); break;
+                        case "Doc": finfo.options = new List<Doc>(options.values as any as Doc[]); break;
+                        default: // string, pointerEvents, dimUnit, dropActionType
+                            finfo.options = new List<string>(options.values as any as string[]); break;
+                    }
+                    finfo.layoutField = options.layoutField;
                     finfo.description = options.description;
                     finfo.type = options.type;
                     infos[key] = finfo;
                 }
+                return infos;
             });
-        }
     }
 
     export let newAccount: boolean = false;
@@ -682,7 +525,7 @@ export namespace Docs {
             // whatever options pertain to this specific prototype
             const options = { title, type, baseProto: true, ...defaultOptions, ...(template.options || {}) };
             options.layout = layout.view?.LayoutString(layout.dataField);
-            const doc = Doc.assign(new Doc(prototypeId, true), { system: true, layoutKey: "layout", ...options });
+            const doc = Doc.assign(new Doc(prototypeId, true), { system: true, layoutKey: "layout", ...options } as any);
             doc.data = template.data;
             doc.layout_keyValue = KeyValueBox.LayoutString("");
             return doc;
@@ -847,7 +690,7 @@ export namespace Docs {
             if (value !== undefined) {
                 deleg[fieldKey] = value;
             }
-            return Doc.assign(deleg, options);
+            return Doc.assign(deleg, options as any);
         }
 
         export function ImageDocument(url: string, options: DocumentOptions = {}) {
@@ -964,8 +807,8 @@ export namespace Docs {
             I.x = options.x;
             I.y = options.y;
             I._backgroundColor = "transparent";
-            I._width = options._width;
-            I._height = options._height;
+            I._width = options._width as number;
+            I._height = options._height as number;
             I._fontFamily = "cursive";
             I.author = Doc.CurrentUserEmail;
             I.rotation = 0;
@@ -1337,7 +1180,7 @@ export namespace DocUtils {
         if (type.indexOf("video") !== -1) {
             ctor = Docs.Create.VideoDocument;
             if (!options._width) options._width = 600;
-            if (!options._height) options._height = options._width * 2 / 3;
+            if (!options._height) options._height = (options._width as number) * 2 / 3;
         }
         if (type.indexOf("audio") !== -1) {
             ctor = Docs.Create.AudioDocument;
@@ -1345,7 +1188,7 @@ export namespace DocUtils {
         if (type.indexOf("pdf") !== -1) {
             ctor = Docs.Create.PdfDocument;
             if (!options._width) options._width = 400;
-            if (!options._height) options._height = options._width * 1200 / 927;
+            if (!options._height) options._height = (options._width as number) * 1200 / 927;
         }
         if (type.indexOf("html") !== -1) {
             if (path.includes(window.location.hostname)) {
@@ -1356,8 +1199,8 @@ export namespace DocUtils {
                         const alias = Doc.MakeAlias(field);
                         alias.x = options.x || 0;
                         alias.y = options.y || 0;
-                        alias._width = options._width || 300;
-                        alias._height = options._height || options._width || 300;
+                        alias._width = (options._width as number) || 300;
+                        alias._height = (options._height as number) || (options._width as number) || 300;
                         return alias;
                     }
                     return undefined;
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index dcaf61fea..9a38c56e7 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -1050,7 +1050,7 @@ export class CurrentUserUtils {
         //     }
         // });
         setTimeout(() => DocServer.UPDATE_SERVER_CACHE(), 2500);
-        doc.fieldInfos = Docs.FieldInfos;
+        doc.fieldInfos = await Docs.setupFieldInfos();
         return doc;
     }
 
@@ -1070,7 +1070,6 @@ export class CurrentUserUtils {
     }
 
     public static async loadUserDocument(id: string) {
-        await Docs.setupFieldInfos();
         this.curr_id = id;
         await rp.get(Utils.prepend("/getUserDocumentIds")).then(ids => {
             const { userDocumentId, sharingDocumentId, linkDatabaseId } = JSON.parse(ids);
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index e1fbea76e..15b98467c 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -276,6 +276,6 @@ export class LightboxTourBtn extends React.Component<LightboxTourBtnProps> {
                 this.props.stepInto();
             },
             StrCast(this.props.tourMap()?.lastElement()?.TourMap)
-        )
+        );
     }
 }
\ No newline at end of file
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;
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 513ef4015..6975c24d1 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -499,7 +499,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         [{ script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, label: "New Folder" }] : Doc.IsSystem(this.doc) ? [] :
             this.fileSysMode && this.doc === Doc.GetProto(this.doc) ?
                 [{ script: ScriptField.MakeFunction(`openOnRight(getAlias(self))`)!, label: "Open Alias" }] :
-                [{ script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, label: "Focus or Open" }];
+                [{ script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, label: "Focus or Open" }]
     truncateTitleWidth = () => NumCast(this.props.treeView.props.Document.treeViewTruncateTitleWidth, this.props.panelWidth());
     onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick));
     onChildDoubleClick = () => (!this.outlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick);
-- 
cgit v1.2.3-70-g09d2


From 1b481cd441cc8bb200906b246b43e4bc5dc53b4e Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 2 Mar 2021 19:52:59 -0500
Subject: added a fitwidth toggle for lightbox.  fixed _showCaption/setting
 _fields to undefined.  updated documentView to use not having fitWidth set as
 a trigger for whether to treat a doc without nativeWidth/Height as if its
 width/height is that.

---
 src/client/documents/Documents.ts                  | 14 ++--
 src/client/views/DocumentDecorations.tsx           |  2 +-
 src/client/views/LightboxView.tsx                  |  5 ++
 src/client/views/PropertiesButtons.tsx             | 30 ++++++++-
 .../views/collections/CollectionStackingView.tsx   | 37 ++++++-----
 .../CollectionMulticolumnView.tsx                  |  6 +-
 .../CollectionMultirowView.tsx                     | 16 ++---
 src/client/views/nodes/DocumentView.tsx            | 75 +++++++++++++---------
 src/client/views/nodes/EquationBox.tsx             | 11 ++--
 src/client/views/nodes/VideoBox.tsx                |  2 +-
 src/fields/Schema.ts                               |  5 +-
 src/fields/util.ts                                 |  2 +-
 12 files changed, 125 insertions(+), 80 deletions(-)

(limited to 'src/client/views/LightboxView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index e270d2ac8..f87c7185c 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -830,7 +830,7 @@ export namespace Docs {
         }
 
         export function KVPDocument(document: Doc, options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.KVP), document, { title: document.title + ".kvp", ...options });
+            return InstanceFromProto(Prototypes.get(DocumentType.KVP), document, { _fitWidth: true, title: document.title + ".kvp", ...options });
         }
 
         export function DocumentDocument(document?: Doc, options: DocumentOptions = {}) {
@@ -860,23 +860,23 @@ export namespace Docs {
         }
 
         export function CarouselDocument(documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Carousel });
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", _fitWidth: true, ...options, _viewType: CollectionViewType.Carousel });
         }
 
         export function Carousel3DDocument(documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Carousel3D });
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", _fitWidth: true, ...options, _viewType: CollectionViewType.Carousel3D });
         }
 
         export function SchemaDocument(schemaHeaders: SchemaHeaderField[], documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaHeaders: schemaHeaders.length ? new List(schemaHeaders) : undefined, ...options, _viewType: CollectionViewType.Schema });
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", _fitWidth: true, schemaHeaders: schemaHeaders.length ? new List(schemaHeaders) : undefined, ...options, _viewType: CollectionViewType.Schema });
         }
 
         export function TreeDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", dontRegisterChildViews: true, ...options, _viewType: CollectionViewType.Tree }, id);
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", _fitWidth: true, dontRegisterChildViews: true, ...options, _viewType: CollectionViewType.Tree }, id);
         }
 
         export function StackingDocument(documents: Array<Doc>, options: DocumentOptions, id?: string, protoId?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Stacking }, id, undefined, protoId);
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", _fitWidth: true, ...options, _viewType: CollectionViewType.Stacking }, id, undefined, protoId);
         }
 
         export function MulticolumnDocument(documents: Array<Doc>, options: DocumentOptions) {
@@ -926,7 +926,7 @@ export namespace Docs {
 
         export function DockDocument(documents: Array<Doc>, config: string, options: DocumentOptions, id?: string) {
             const inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { freezeChildren: "remove|add", treeViewDefaultExpandedView: "data", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id);
-            const tabs = TreeDocument(documents, { title: "On-Screen Tabs", freezeChildren: "remove|add", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data", system: true });
+            const tabs = TreeDocument(documents, { title: "On-Screen Tabs", freezeChildren: "remove|add", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data", _fitWidth: true, system: true });
             const all = TreeDocument([], { title: "Off-Screen Tabs", freezeChildren: "add", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data", system: true });
             Doc.GetProto(inst).data = new List<Doc>([tabs, all]);
             return inst;
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 5b7394c42..1e3c0ba92 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -479,7 +479,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
         SelectionManager.Views().map(dv => {
             const hgts = this._dragHeights.get(dv.layoutDoc);
             if (hgts && hgts.lowest < hgts.start && hgts.lowest <= 20) {
-                dv.nativeWidth > 0 && Doc.toggleNativeDimensions(dv.layoutDoc, dv.ContentScale(), dv.props.PanelWidth(), dv.props.PanelHeight());
+                dv.effectiveNativeWidth > 0 && Doc.toggleNativeDimensions(dv.layoutDoc, dv.ContentScale(), dv.props.PanelWidth(), dv.props.PanelHeight());
                 if (dv.layoutDoc._autoHeight) dv.layoutDoc._autoHeight = false;
                 setTimeout(() => dv.layoutDoc._autoHeight = true);
             }
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index 15b98467c..3fc72c45c 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -247,6 +247,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                         ContainingCollectionDoc={undefined}
                         renderDepth={0} />
                 </div>
+
                 {this.navBtn(0, undefined, this.props.PanelHeight / 2 - 12.50, "chevron-left",
                     () => LightboxView.LightboxDoc && LightboxView._history?.length ? "" : "none", e => {
                         e.stopPropagation();
@@ -258,6 +259,10 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                         LightboxView.Next();
                     })}
                 <LightboxTourBtn navBtn={this.navBtn} future={this.future} stepInto={this.stepInto} tourMap={this.tourMap} />
+                <div className="lightboxView-navBtn" title={"toggle fit width"} style={{ position: "absolute", right: 10, top: 10, color: "white" }}
+                    onClick={e => { e.stopPropagation(); LightboxView.LightboxDoc!._fitWidth = !LightboxView.LightboxDoc!._fitWidth }}>
+                    <FontAwesomeIcon icon={"arrows-alt-h"} size="2x" />
+                </div>
             </div>;
     }
 }
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index e9963bce9..e418a6f3c 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -260,7 +260,10 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @undoBatch
     @action
     setCaption = () => {
-        SelectionManager.Views().forEach(dv => dv.rootDoc._showCaption = dv.rootDoc._showCaption === undefined ? "caption" : undefined);
+        SelectionManager.Views().forEach(dv => {
+            dv.rootDoc._showCaption = dv.rootDoc._showCaption === undefined ? "caption" : undefined;
+            console.log("caption = " + dv.rootDoc._showCaption);
+        });
     }
 
     @computed
@@ -426,6 +429,14 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         }
     }
 
+    @action @undoBatch
+    changeFitWidth = () => {
+        if (this.selectedDoc) {
+            if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => dv.rootDoc._fitWidth = !dv.rootDoc._fitWidth);
+            else this.selectedDoc._fitWidth = !this.selectedDoc._fitWidth;
+        }
+    }
+
     @action @undoBatch
     changeClusters = () => {
         if (this.selectedDoc) {
@@ -448,6 +459,20 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         </Tooltip>;
     }
 
+    @computed
+    get fitWidthButton() {
+        const targetDoc = this.selectedDoc;
+        return !targetDoc ? (null) : <Tooltip
+            title={<><div className="dash-tooltip">{this.selectedDoc?._fitWidth ? "Stop Fitting Width" : "Fit Width"}</div></>} placement="top">
+            <div>
+                <div className={`propertiesButtons-linkButton-empty toggle-${targetDoc._fitWidth ? "on" : "off"}`} onPointerDown={this.changeFitWidth}>
+                    <FontAwesomeIcon className="documentdecorations-icon" icon="arrows-alt-h" size="lg" />
+                </div>
+                <div className="propertiesButtons-title"> {this.selectedDoc?._fitWidth ? "unfit" : "fit"} </div>
+            </div>
+        </Tooltip>;
+    }
+
     @undoBatch
     @action
     private makeMask = () => {
@@ -521,6 +546,9 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             <div className="propertiesButtons-button" style={{ display: !isFreeForm && !isText ? "none" : "" }}>
                 {this.fitContentButton}
             </div>
+            <div className="propertiesButtons-button">
+                {this.fitWidthButton}
+            </div>
             <div className="propertiesButtons-button" style={{ display: !isInk ? "none" : "" }}>
                 {this.maskButton}
             </div>
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index b5ce4b443..7152f4272 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -29,6 +29,7 @@ import "./CollectionStackingView.scss";
 import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn";
 import { CollectionSubView } from "./CollectionSubView";
 import { CollectionViewType } from "./CollectionView";
+import { LightboxView } from "../LightboxView";
 const _global = (window /* browser */ || global /* node */) as any;
 
 type StackingDocument = makeInterface<[typeof collectionSchema, typeof documentSchema]>;
@@ -204,10 +205,10 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
         const dataDoc = (!doc.isTemplateDoc && !doc.isTemplateForField && !doc.PARAMS) ? undefined : this.props.DataDoc;
         const height = () => this.getDocHeight(doc);
 
-        let dref: Opt<HTMLDivElement>;
+        let dref: Opt<DocumentView>;
         const stackedDocTransform = () => this.getDocTransform(doc, dref);
         this._docXfs.push({ stackedDocTransform, width, height });
-        return <DocumentView ref={r => dref = r?.ContentDiv ? r.ContentDiv : undefined}
+        return <DocumentView ref={r => dref = r || undefined}
             Document={doc}
             DataDoc={dataDoc || (!Doc.AreProtosEqual(doc[DataSym], doc) && doc[DataSym])}
             renderDepth={this.props.renderDepth + 1}
@@ -247,18 +248,24 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
         />;
     }
 
+    getDocTransform(doc: Doc, dref?: DocumentView) {
+        const y = this._scroll; // required for document decorations to update when the text box container is scrolled
+        const { scale, translateX, translateY } = Utils.GetScreenTransform(dref?.ContentDiv || undefined);
+        // the document view may center its contents and if so, will prepend that onto the screenToLocalTansform.  so we have to subtract that off 
+        return new Transform(- translateX - (dref?.centeringX || 0), - translateY - (dref?.centeringY || 0), 1).scale(this.props.ScreenToLocalTransform().Scale * (this.props.scaling?.() || 1));
+    }
     getDocWidth(d?: Doc) {
         if (!d) return 0;
-        const layoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.());
-        const nw = Doc.NativeWidth(layoutDoc);
-        return Math.min(nw && !this.layoutDoc._columnsFill ? d[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns);
+        const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.());
+        const nw = Doc.NativeWidth(childLayoutDoc) || (childLayoutDoc._fitWidth ? 0 : d[WidthSym]());
+        return Math.min(nw && !this.layoutDoc._columnsFill ? (this.props.scaling?.() || 1) * d[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns);
     }
     getDocHeight(d?: Doc) {
         if (!d) return 0;
         const childDataDoc = (!d.isTemplateDoc && !d.isTemplateForField && !d.PARAMS) ? undefined : this.props.DataDoc;
         const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.());
-        const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc);
-        const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc);
+        const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (childLayoutDoc._fitWidth ? 0 : d[WidthSym]());
+        const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (childLayoutDoc._fitWidth ? 0 : d[HeightSym]());
         let wid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1);
         if (!this.layoutDoc._columnsFill) wid = Math.min(wid, childLayoutDoc[WidthSym]());
         const hllimit = NumCast(this.layoutDoc.childLimitHeight, -1);
@@ -268,7 +275,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
             return Math.min(hllimit === 0 ? this.props.PanelWidth() : hllimit === -1 ? 10000 : hllimit, wid * aspect);
         }
         return childLayoutDoc._fitWidth ?
-            (!nh ? this.props.PanelHeight() - 2 * this.yMargin :
+            (!nh ? Math.min(NumCast(childLayoutDoc.height, 10000) * (this.props.scaling?.() || 1), this.props.PanelHeight() - 2 * this.yMargin) :
                 Math.min(wid * nh / (nw || 1), this.layoutDoc._autoHeight ? 100000 : this.props.PanelHeight() - 2 * this.yMargin)) :
             Math.min(hllimit === 0 ? this.props.PanelWidth() : hllimit === -1 ? 10000 : hllimit, Math.max(20, childLayoutDoc[HeightSym]()));
     }
@@ -361,8 +368,8 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
         const cols = () => this.isStackingView ? 1 : Math.max(1, Math.min(this.filteredChildren.length,
             Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap))));
         return <CollectionStackingViewFieldColumn
-            unobserveHeight={(ref) => this.refList.splice(this.refList.indexOf(ref), 1)}
-            observeHeight={(ref) => {
+            unobserveHeight={ref => this.refList.splice(this.refList.indexOf(ref), 1)}
+            observeHeight={ref => {
                 if (ref) {
                     this.refList.push(ref);
                     const doc = this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc;
@@ -371,7 +378,9 @@ 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", "")))));
-                            this.props.setHeight(height * NumCast(Doc.Layout(doc)._viewScale, 1));
+                            if (!LightboxView.IsLightboxDocView(this.props.docViewPath())) {
+                                this.props.setHeight(height * NumCast(Doc.Layout(doc)._viewScale, 1));
+                            }
                         }
                     }));
                     this.observer.observe(ref);
@@ -390,12 +399,6 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
         />;
     }
 
-    getDocTransform(doc: Doc, dref?: HTMLDivElement) {
-        const y = this._scroll; // required for document decorations to update when the text box container is scrolled
-        const { scale, translateX, translateY } = Utils.GetScreenTransform(dref);
-        return new Transform(-translateX, -translateY, 1).scale(this.props.ScreenToLocalTransform().Scale);
-    }
-
     sectionMasonry = (heading: SchemaHeaderField | undefined, docList: Doc[], first: boolean) => {
         const key = this.pivotField;
         let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined;
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index e51417f64..d23f3309e 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -217,8 +217,8 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
             Document={layout}
             DataDoc={layout.resolvedDataDoc as Doc}
             styleProvider={this.props.styleProvider}
-            layerProvider={undefined}
-            docViewPath={returnEmptyDoclist}
+            layerProvider={this.props.layerProvider}
+            docViewPath={this.props.docViewPath}
             LayoutTemplate={this.props.childLayoutTemplate}
             LayoutTemplateString={this.props.childLayoutString}
             freezeDimensions={this.props.childFreezeDimensions}
@@ -257,7 +257,7 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
         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 dxf = () => this.lookupIndividualTransform(layout).translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin)).scale((this.props.scaling?.() || 1));
             const width = () => this.lookupPixels(layout);
             const height = () => PanelHeight() - 2 * NumCast(Document._yMargin) - (BoolCast(Document.showWidthLabels) ? 20 : 0);
             collector.push(
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index d61a2bb72..641ae6ce1 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -217,8 +217,8 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
             Document={layout}
             DataDoc={layout.resolvedDataDoc as Doc}
             styleProvider={this.props.styleProvider}
-            layerProvider={undefined}
-            docViewPath={returnEmptyDoclist}
+            layerProvider={this.props.layerProvider}
+            docViewPath={this.props.docViewPath}
             LayoutTemplate={this.props.childLayoutTemplate}
             LayoutTemplateString={this.props.childLayoutString}
             freezeDimensions={this.props.childFreezeDimensions}
@@ -257,19 +257,13 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
         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 dxf = () => this.lookupIndividualTransform(layout).translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin)).scale((this.props.scaling?.() || 1));
             const height = () => this.lookupPixels(layout);
             const width = () => PanelWidth() - 2 * NumCast(Document._xMargin) - (BoolCast(Document.showWidthLabels) ? 20 : 0);
             collector.push(
-                <div
-                    className={"document-wrapper"}
-                    key={"wrapper" + i}
-                >
+                <div className={"document-wrapper"} key={"wrapper" + i} >
                     {this.getDisplayDoc(layout, dxf, width, height)}
-                    <HeightLabel
-                        layout={layout}
-                        collectionDoc={Document}
-                    />
+                    <HeightLabel layout={layout} collectionDoc={Document} />
                 </div>,
                 <ResizeBar
                     height={resizerHeight}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index e5bd14809..c86863ed8 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -997,30 +997,40 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
     @computed get docViewPath() { return this.props.docViewPath ? [...this.props.docViewPath(), this] : [this]; }
     @computed get layoutDoc() { return Doc.Layout(this.Document, this.props.LayoutTemplate?.()); }
-    @computed get nativeWidth() { return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions)); }
-    @computed get nativeHeight() { return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions) || 0); }
+    @computed get nativeWidth() {
+        return this.docView?._componentView?.reverseNativeScaling?.() ? 0 :
+            returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions));
+    }
+    @computed get nativeHeight() {
+        return this.docView?._componentView?.reverseNativeScaling?.() ? 0 :
+            returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions));
+    }
+    shouldNotScale = () => this.layoutDoc._fitWidth || [CollectionViewType.Docking, CollectionViewType.Tree].includes(this.Document._viewType as any);
+    @computed get effectiveNativeWidth() { return this.nativeWidth || (this.shouldNotScale() ? 0 : NumCast(this.layoutDoc.width)); }
+    @computed get effectiveNativeHeight() { return this.nativeHeight || (this.shouldNotScale() ? 0 : NumCast(this.layoutDoc.height)); }
     @computed get nativeScaling() {
-        if (this.nativeWidth && (this.layoutDoc?._fitWidth || this.props.PanelHeight() / this.nativeHeight > this.props.PanelWidth() / this.nativeWidth)) {
-            return this.props.PanelWidth() / this.nativeWidth;  // width-limited or fitWidth
+        const minTextScale = this.Document.type === DocumentType.RTF ? 0.1 : 0;
+        if (this.effectiveNativeWidth && (this.layoutDoc?._fitWidth || this.props.PanelHeight() / this.effectiveNativeHeight > this.props.PanelWidth() / this.effectiveNativeWidth)) {
+            return Math.max(minTextScale, this.props.PanelWidth() / this.effectiveNativeWidth);  // width-limited or fitWidth
         }
-        return this.nativeWidth && this.nativeHeight ? this.props.PanelHeight() / this.nativeHeight : 1; // height-limited or unscaled
+        return this.effectiveNativeWidth && this.effectiveNativeHeight ? Math.max(minTextScale, this.props.PanelHeight() / this.effectiveNativeHeight) : 1; // height-limited or unscaled
     }
 
-    @computed get panelWidth() { return this.nativeWidth ? this.nativeWidth * this.nativeScaling : this.props.PanelWidth(); }
+    @computed get panelWidth() { return this.effectiveNativeWidth ? this.effectiveNativeWidth * this.nativeScaling : this.props.PanelWidth(); }
     @computed get panelHeight() {
-        if (this.nativeHeight) {
+        if (this.effectiveNativeHeight) {
             return Math.min(this.props.PanelHeight(),
                 this.props.Document._fitWidth ?
-                    Math.max(NumCast(this.props.Document._height), NumCast(((this.props.Document.scrollHeight || 0) as number) * this.props.PanelWidth() / this.nativeWidth, this.props.PanelHeight())) :
-                    this.nativeHeight * this.nativeScaling
+                    Math.max(NumCast(this.props.Document._height), NumCast(((this.props.Document.scrollHeight || 0) as number) * this.props.PanelWidth() / this.effectiveNativeWidth, this.props.PanelHeight())) :
+                    this.effectiveNativeHeight * this.nativeScaling
             );
         }
         return this.props.PanelHeight();
     }
-    @computed get Xshift() { return this.nativeWidth ? (this.props.PanelWidth() - this.nativeWidth * this.nativeScaling) / 2 : 0; }
-    @computed get YShift() { return this.nativeWidth && this.nativeHeight && Math.abs(this.Xshift) < 0.001 ? (this.props.PanelHeight() - this.nativeHeight * this.nativeScaling) / 2 : 0; }
+    @computed get Xshift() { return this.effectiveNativeWidth ? (this.props.PanelWidth() - this.effectiveNativeWidth * this.nativeScaling) / 2 : 0; }
+    @computed get Yshift() { return this.effectiveNativeWidth && this.effectiveNativeHeight && Math.abs(this.Xshift) < 0.001 ? (this.props.PanelHeight() - this.effectiveNativeHeight * this.nativeScaling) / 2 : 0; }
     @computed get centeringX() { return this.props.dontCenter?.includes("x") ? 0 : this.Xshift; }
-    @computed get centeringY() { return this.props.Document._fitWidth || this.props.dontCenter?.includes("y") ? 0 : this.YShift; }
+    @computed get centeringY() { return this.props.Document._fitWidth || this.props.dontCenter?.includes("y") ? 0 : this.Yshift; }
 
     toggleNativeDimensions = () => this.docView && Doc.toggleNativeDimensions(this.layoutDoc, this.docView.ContentScale, this.props.PanelWidth(), this.props.PanelHeight());
     contentsActive = () => this.docView?.contentsActive();
@@ -1067,8 +1077,8 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     docViewPathFunc = () => this.docViewPath;
     isSelected = (outsideReaction?: boolean) => SelectionManager.IsSelected(this, outsideReaction);
     select = (extendSelection: boolean) => SelectionManager.SelectView(this, !SelectionManager.Views().some(v => v.props.Document === this.props.ContainingCollectionDoc) && extendSelection);
-    NativeWidth = () => this.nativeWidth;
-    NativeHeight = () => this.nativeHeight;
+    NativeWidth = () => this.effectiveNativeWidth;
+    NativeHeight = () => this.effectiveNativeHeight;
     PanelWidth = () => this.panelWidth;
     PanelHeight = () => this.panelHeight;
     ContentScale = () => this.nativeScaling;
@@ -1093,31 +1103,32 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
     render() {
         TraceMobx();
-        const internalProps = {
-            ...this.props,
-            DocumentView: this.selfView,
-            viewPath: this.docViewPathFunc,
-            PanelWidth: this.PanelWidth,
-            PanelHeight: this.PanelHeight,
-            NativeWidth: this.NativeWidth,
-            NativeHeight: this.NativeHeight,
-            isSelected: this.isSelected,
-            select: this.select,
-            ContentScaling: this.ContentScale,
-            ScreenToLocalTransform: this.screenToLocalTransform,
-            focus: this.props.focus || emptyFunction,
-            bringToFront: emptyFunction,
-        };
+        const xshift = this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Xshift) <= 0.001 ? this.props.PanelWidth() : undefined;
+        const yshift = this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Yshift) <= 0.001 ? this.props.PanelHeight() : undefined;
         return (<div className="contentFittingDocumentView">
             {!this.props.Document || !this.props.PanelWidth() ? (null) : (
                 <div className="contentFittingDocumentView-previewDoc" ref={this.ContentRef}
                     style={{
                         position: this.props.Document.isInkMask ? "absolute" : undefined,
                         transform: `translate(${this.centeringX}px, ${this.centeringY}px)`,
-                        width: this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Xshift) > 0.001 ? `${100 * (this.props.PanelWidth() - this.Xshift * 2) / this.props.PanelWidth()}%` : this.props.PanelWidth(),
-                        height: this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.YShift) > 0.001 ? this.props.Document._fitWidth ? `${this.panelHeight}px` : `${100 * this.nativeHeight / this.nativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%` : this.props.PanelHeight(),
+                        width: xshift ?? `${100 * (this.props.PanelWidth() - this.Xshift * 2) / this.props.PanelWidth()}%`,
+                        height: yshift ?? this.props.Document._fitWidth ? `${this.panelHeight}px` :
+                            `${100 * this.effectiveNativeHeight / this.effectiveNativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%`,
                     }}>
-                    <DocumentViewInternal {...this.props} {...internalProps} ref={action((r: DocumentViewInternal | null) => this.docView = r)} />
+                    <DocumentViewInternal {...this.props}
+                        DocumentView={this.selfView}
+                        viewPath={this.docViewPathFunc}
+                        PanelWidth={this.PanelWidth}
+                        PanelHeight={this.PanelHeight}
+                        NativeWidth={this.NativeWidth}
+                        NativeHeight={this.NativeHeight}
+                        isSelected={this.isSelected}
+                        select={this.select}
+                        ContentScaling={this.ContentScale}
+                        ScreenToLocalTransform={this.screenToLocalTransform}
+                        focus={this.props.focus || emptyFunction}
+                        bringToFront={emptyFunction}
+                        ref={action((r: DocumentViewInternal | null) => this.docView = r)} />
                 </div>)}
         </div>);
     }
diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx
index 7f9fc342a..5bc73d5d9 100644
--- a/src/client/views/nodes/EquationBox.tsx
+++ b/src/client/views/nodes/EquationBox.tsx
@@ -56,10 +56,13 @@ export class EquationBox extends ViewBoxBaseComponent<FieldViewProps, EquationDo
     }
     onChange = (str: string) => {
         this.dataDoc.text = str;
-        const _height = Number(getComputedStyle(this._ref.current!.element.current).height.replace("px", ""));
-        const _width = Number(getComputedStyle(this._ref.current!.element.current).width.replace("px", ""));
-        this.layoutDoc._width = Math.max(35, _width);
-        this.layoutDoc._height = Math.max(25, _height);
+        const style = this._ref.current && getComputedStyle(this._ref.current.element.current);
+        if (style) {
+            const _height = Number(style.height.replace("px", ""));
+            const _width = Number(style.width.replace("px", ""));
+            this.layoutDoc._width = Math.max(35, _width);
+            this.layoutDoc._height = Math.max(25, _height);
+        }
     }
     render() {
         TraceMobx();
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 589a6dd24..6afc2258a 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -482,7 +482,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
 
     playing = () => this._playing;
     isActiveChild = () => this._isChildActive;
-    timelineWhenActiveChanged = (isActive: boolean) => this.props.whenActiveChanged(runInAction(() => this._isChildActive = isActive));
+    timelineWhenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive));
     timelineScreenToLocal = () => this.props.ScreenToLocalTransform().scale(this.scaling()).translate(0, -this.heightPercent / 100 * this.props.PanelHeight());
     setAnchorTime = (time: number) => this.player!.currentTime = this.layoutDoc._currentTimecode = time;
     timelineHeight = () => this.props.PanelHeight() * (100 - this.heightPercent) / 100;
diff --git a/src/fields/Schema.ts b/src/fields/Schema.ts
index 4607e0fd5..78f8a6bfb 100644
--- a/src/fields/Schema.ts
+++ b/src/fields/Schema.ts
@@ -3,6 +3,7 @@ import { Doc, Field } from "./Doc";
 import { ObjectField } from "./ObjectField";
 import { RefField } from "./RefField";
 import { SelfProxy } from "./FieldSymbols";
+import { List } from "./List";
 
 type AllToInterface<T extends Interface[]> = {
     1: ToInterface<Head<T>> & AllToInterface<Tail<T>>,
@@ -67,9 +68,9 @@ export function makeInterface<T extends Interface[]>(...schemas: T): InterfaceFu
     return function (doc?: Doc | Doc[]) {
         if (doc instanceof Doc || doc === undefined) {
             return fn(doc || new Doc);
-        } else {
+        } else if (doc instanceof List) {
             return doc.map(fn);
-        }
+        } else return {};
     };
 }
 
diff --git a/src/fields/util.ts b/src/fields/util.ts
index 7955fc9fb..36c765dd0 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -289,7 +289,7 @@ export function setter(target: any, in_prop: string | symbol | number, value: an
         //     console.log(prop + " is deprecated - switch to _" + prop);
         //     prop = "_" + prop;
         // }
-        if (!prop.startsWith("__") && value !== undefined) prop = prop.substring(1);
+        if (!prop.startsWith("__")) prop = prop.substring(1);
         if (target.__LAYOUT__) {
             target.__LAYOUT__[prop] = value;
             return true;
-- 
cgit v1.2.3-70-g09d2

