From 3e6f24e4ac4a4b64620d8c9f614f214f8f1c7b94 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 17 Sep 2019 19:47:05 -0400
Subject: cleanup for animating document icon collapse/expand - still need to
 fix for docs without native dimensions.   lots of lint fixes.

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

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

diff --git a/src/client/views/nodes/ButtonBox.tsx b/src/client/views/nodes/ButtonBox.tsx
index 68d3b8ae1..eebf6c167 100644
--- a/src/client/views/nodes/ButtonBox.tsx
+++ b/src/client/views/nodes/ButtonBox.tsx
@@ -49,7 +49,7 @@ export class ButtonBox extends DocComponent<FieldViewProps, ButtonDocument>(Butt
         funcs.push({
             description: "Clear Script Params", event: () => {
                 let params = Cast(this.props.Document.buttonParams, listSpec("string"));
-                params && params.map(p => this.props.Document[p] = undefined)
+                params && params.map(p => this.props.Document[p] = undefined);
             }, icon: "trash"
         });
 
-- 
cgit v1.2.3-70-g09d2


From b93a9b48a00571e07859f5b6c6ade1cdf764e8ea Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 18 Sep 2019 00:20:58 -0400
Subject: cleaned up custom template layouts

---
 src/client/util/DragManager.ts                     |   2 +-
 src/client/views/DocumentDecorations.tsx           |  27 ++--
 src/client/views/TemplateMenu.tsx                  |   2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   4 +-
 src/client/views/nodes/ButtonBox.tsx               |   4 +-
 src/client/views/nodes/DocumentContentsView.tsx    |   9 +-
 src/client/views/nodes/DocumentView.tsx            | 166 +++++++--------------
 src/new_fields/Doc.ts                              |  16 +-
 8 files changed, 80 insertions(+), 150 deletions(-)

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 252accefa..cb55e1bc6 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -250,7 +250,7 @@ export namespace DragManager {
             });
     }
 
-    export function StartButtonDrag(eles: HTMLElement[], script: string, title: string, vars: { [name: string]: Field }, params: string[], initialize?: (button: Doc) => void, downX: number, downY: number, options?: DragOptions) {
+    export function StartButtonDrag(eles: HTMLElement[], script: string, title: string, vars: { [name: string]: Field }, params: string[], initialize: (button: Doc) => void, downX: number, downY: number, options?: DragOptions) {
         let dragData = new DragManager.DocumentDragData([]);
         runInAction(() => StartDragFunctions.map(func => func()));
         StartDrag(eles, dragData, downX, downY, options, options && options.finishDrag ? options.finishDrag :
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 9a2105467..2826f4422 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -1,40 +1,37 @@
-import { library, IconProp } from '@fortawesome/fontawesome-svg-core';
-import { faLink, faTag, faTimes, faArrowAltCircleDown, faArrowAltCircleUp, faCheckCircle, faStopCircle, faCloudUploadAlt, faSyncAlt, faShare } from '@fortawesome/free-solid-svg-icons';
+import { IconProp, library } from '@fortawesome/fontawesome-svg-core';
+import { faArrowAltCircleDown, faArrowAltCircleUp, faCheckCircle, faCloudUploadAlt, faLink, faShare, faStopCircle, faSyncAlt, faTag, faTimes } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { action, computed, observable, reaction, runInAction, trace } from "mobx";
+import { action, computed, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
 import { Doc, DocListCastAsync } from "../../new_fields/Doc";
 import { List } from "../../new_fields/List";
+import { ObjectField } from '../../new_fields/ObjectField';
+import { RichTextField } from '../../new_fields/RichTextField';
 import { BoolCast, Cast, NumCast, StrCast } from "../../new_fields/Types";
 import { URLField } from '../../new_fields/URLField';
+import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
 import { emptyFunction, Utils } from "../../Utils";
+import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils';
 import { Docs, DocUtils } from "../documents/Documents";
 import { DocumentManager } from "../util/DocumentManager";
 import { DragLinksAsDocuments, DragManager } from "../util/DragManager";
+import { LinkManager } from '../util/LinkManager';
 import { SelectionManager } from "../util/SelectionManager";
 import { undoBatch, UndoManager } from "../util/UndoManager";
 import { MINIMIZED_ICON_SIZE } from "../views/globalCssVariables.scss";
 import { CollectionView } from "./collections/CollectionView";
 import './DocumentDecorations.scss';
+import { LinkMenu } from "./linking/LinkMenu";
+import { MetadataEntryMenu } from './MetadataEntryMenu';
+import { PositionDocument } from './nodes/CollectionFreeFormDocumentView';
 import { DocumentView } from "./nodes/DocumentView";
 import { FieldView } from "./nodes/FieldView";
 import { FormattedTextBox, GoogleRef } from "./nodes/FormattedTextBox";
 import { IconBox } from "./nodes/IconBox";
-import { LinkMenu } from "./linking/LinkMenu";
+import { ImageBox } from './nodes/ImageBox';
 import { TemplateMenu } from "./TemplateMenu";
 import { Template, Templates } from "./Templates";
 import React = require("react");
-import { RichTextField } from '../../new_fields/RichTextField';
-import { LinkManager } from '../util/LinkManager';
-import { MetadataEntryMenu } from './MetadataEntryMenu';
-import { ImageBox } from './nodes/ImageBox';
-import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
-import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils';
-import { ObjectField } from '../../new_fields/ObjectField';
-import { DocServer } from '../DocServer';
-import { CompileScript } from '../util/Scripting';
-import { ComputedField } from '../../new_fields/ScriptField';
-import { PositionDocument } from './nodes/CollectionFreeFormDocumentView';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index d57a72dad..397bb14a4 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -123,7 +123,7 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
                 <div title="Template Options" className="templating-button" onClick={() => this.toggleTemplateActivity()}>+</div>
                 <ul id="template-list" ref={this.dragRef} style={{ display: this._hidden ? "none" : "block" }}>
                     {templateMenu}
-                    <button onClick={this.toggleCustom}>{this.props.docs[0].Document.nativeLayout ? "Native" : "Custom"}</button>
+                    <button onClick={this.toggleCustom}>{typeof this.props.docs[0].Document.layout === "string" ? "Custom" : "Native"}</button>
                     <button onClick={this.toggleFloat}>Float</button>
                     {/* <button onClick={this.clearTemplates}>Clear</button> */}
                 </ul>
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 8d392d764..0c559d83d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -903,9 +903,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             description: "Add Note ...",
             subitems: DocListCast((CurrentUserUtils.UserDocument.noteTypes as Doc).data).map((note, i) => ({
                 description: (i + 1) + ": " + StrCast(note.title),
-                event: ({ x, y }) => this.addLiveTextBox(Docs.Create.TextDocument({ width: 200, height: 100, x: this.getTransform().transformPoint(x, y)[0], y: this.getTransform().transformPoint(x, y)[1], autoHeight: true, layout: note, title: StrCast(note.title) })),
+                event: (args: { x: number, y: number }) => this.addLiveTextBox(Docs.Create.TextDocument({ width: 200, height: 100, x: this.getTransform().transformPoint(args.x, args.y)[0], y: this.getTransform().transformPoint(args.x, args.y)[1], autoHeight: true, layout: note, title: StrCast(note.title) })),
                 icon: "eye"
-            })),
+            })) as ContextMenuProps[],
             icon: "eye"
         });
         ContextMenu.Instance.addItem({ description: "Freeform Options ...", subitems: layoutItems, icon: "eye" });
diff --git a/src/client/views/nodes/ButtonBox.tsx b/src/client/views/nodes/ButtonBox.tsx
index eebf6c167..f08ea4891 100644
--- a/src/client/views/nodes/ButtonBox.tsx
+++ b/src/client/views/nodes/ButtonBox.tsx
@@ -3,7 +3,7 @@ import { faEdit } from '@fortawesome/free-regular-svg-icons';
 import { action, computed } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { Doc, DocListCastAsync } from '../../../new_fields/Doc';
+import { Doc, DocListCastAsync, DocListCast } from '../../../new_fields/Doc';
 import { List } from '../../../new_fields/List';
 import { createSchema, makeInterface, listSpec } from '../../../new_fields/Schema';
 import { ScriptField } from '../../../new_fields/ScriptField';
@@ -68,7 +68,7 @@ export class ButtonBox extends DocComponent<FieldViewProps, ButtonDocument>(Butt
     render() {
         let params = Cast(this.props.Document.buttonParams, listSpec("string"));
         let missingParams = params && params.filter(p => this.props.Document[p] === undefined);
-        params && params.map(async p => await DocListCastAsync(this.props.Document[p])); // bcz: really hacky form of prefetching ... 
+        params && params.map(p => DocListCast(this.props.Document[p])); // bcz: really hacky form of prefetching ... 
         return (
             <div className="buttonBox-outerDiv" ref={this.createDropTarget} onContextMenu={this.specificContextMenu}>
                 <div className="buttonBox-mainButton" style={{ background: StrCast(this.props.Document.backgroundColor), color: StrCast(this.props.Document.color, "black") }} >
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index d0e117fe4..3c3cc0d91 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -93,13 +93,6 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
         return { props: list };
     }
 
-    @computed get templates(): List<string> {
-        let field = this.props.Document.templates;
-        if (field && field instanceof List) {
-            return field;
-        }
-        return new List<string>();
-    }
     @computed get finalLayout() {
         return this.props.layoutKey === "overlayLayout" ? "<div/>" : this.layout;
     }
@@ -107,7 +100,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
     render() {
         let self = this;
         if (this.props.renderDepth > 7) return (null);
-        if (!this.layout && (this.props.layoutKey !== "overlayLayout" || !this.templates.length)) return (null);
+        if (!this.layout && this.props.layoutKey !== "overlayLayout") return (null);
         return <ObserverJsxParser
             blacklistedAttrs={[]}
             components={{ FormattedTextBox, ImageBox, IconBox, DirectoryImportBox, DragBox, ButtonBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox, PresBox, YoutubeBox, LinkFollowBox }}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 2c7df334f..152dc3ddd 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -377,56 +377,31 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     deleteClicked = (): void => { SelectionManager.DeselectAll(); this.props.removeDocument && this.props.removeDocument(this.props.Document); }
 
     @undoBatch
-    makeNativeViewClicked = (): void => {
-        makeNativeView(this.props.Document);
-    }
+    makeNativeViewClicked = (): void => { swapViews(this.props.Document, "layoutNative", "layoutCustom"); }
+
     @undoBatch
-    makeCustomViewClicked = (): void => {
-        this.props.Document.nativeLayout = this.Document.layout;
-        this.props.Document.nativeType = this.Document.type;
-        this.props.Document.nonCustomAutoHeight = this.Document.autoHeight;
-        this.props.Document.nonCustomWidth = this.Document.width;
-        this.props.Document.nonCustomHeight = this.Document.height;
-        this.props.Document.nonCustomNativeWidth = this.Document.nativeWidth;
-        this.props.Document.nonCustomNativeHeight = this.Document.nativeHeight;
-        this.props.Document.nonCustomIgnoreAspect = this.Document.ignoreAspect;
-        PromiseValue(Cast(this.props.Document.customLayout, Doc)).then(custom => {
-            if (custom) {
-                this.Document.type = DocumentType.TEMPLATE;
-                this.props.Document.layout = custom;
-                !custom.nativeWidth && (this.Document.nativeWidth = 0);
-                !custom.nativeHeight && (this.Document.nativeHeight = 0);
-                !custom.nativeWidth && (this.Document.ignoreAspect = true);
-                this.Document.autoHeight = BoolCast(this.Document.customAutoHeight);
-                this.Document.width = NumCast(this.props.Document.customWidth);
-                this.Document.height = NumCast(this.props.Document.customHeight);
-                this.Document.nativeWidth = NumCast(this.props.Document.customNativeWidth);
-                this.Document.nativeHeight = NumCast(this.props.Document.customNativeHeight);
-                this.Document.ignoreAspect = BoolCast(this.Document.customIgnoreAspect);
-                this.props.Document.customAutoHeight = undefined;
-                this.props.Document.customWidth = undefined;
-                this.props.Document.customHeight = undefined;
-                this.props.Document.customNativeWidth = undefined;
-                this.props.Document.customNativeHeight = undefined;
-                this.props.Document.customIgnoreAspect = undefined;
-            } else {
-                let options = { title: "data", width: (this.Document.width || 0), x: -(this.Document.width || 0) / 2, y: - (this.Document.height || 0) / 2, };
-                let fieldTemplate = this.Document.type === DocumentType.TEXT ? Docs.Create.TextDocument(options) :
-                    this.Document.type === DocumentType.VID ? Docs.Create.VideoDocument("http://www.cs.brown.edu", options) :
-                        Docs.Create.ImageDocument("http://www.cs.brown.edu", options);
+    makeCustomViewClicked = async () => {
+        if (this.props.Document.layoutCustom === undefined) {
+            Doc.GetProto(this.dataDoc || this.props.Document).layoutNative = Doc.MakeTitled("layoutNative");
+            await swapViews(this.props.Document, "", "layoutNative");
 
-                fieldTemplate.backgroundColor = this.Document.backgroundColor;
-                fieldTemplate.heading = 1;
-                fieldTemplate.autoHeight = true;
+            let options = { title: "data", width: (this.Document.width || 0), x: -(this.Document.width || 0) / 2, y: - (this.Document.height || 0) / 2, };
+            let fieldTemplate = this.Document.type === DocumentType.TEXT ? Docs.Create.TextDocument(options) :
+                this.Document.type === DocumentType.VID ? Docs.Create.VideoDocument("http://www.cs.brown.edu", options) :
+                    Docs.Create.ImageDocument("http://www.cs.brown.edu", options);
 
-                let docTemplate = Docs.Create.FreeformDocument([fieldTemplate], { title: this.Document.title + "layout", width: (this.Document.width || 0) + 20, height: Math.max(100, (this.Document.height || 0) + 45) });
-                let proto = Doc.GetProto(docTemplate);
-                Doc.MakeMetadataFieldTemplate(fieldTemplate, proto, true);
+            fieldTemplate.backgroundColor = this.Document.backgroundColor;
+            fieldTemplate.heading = 1;
+            fieldTemplate.autoHeight = true;
 
-                Doc.ApplyTemplateTo(docTemplate, this.props.Document, undefined, false);
-                Doc.GetProto(this.dataDoc || this.props.Document).customLayout = this.Document.layout;
-            }
-        });
+            let docTemplate = Docs.Create.FreeformDocument([fieldTemplate], { title: this.Document.title + "_layout", width: (this.Document.width || 0) + 20, height: Math.max(100, (this.Document.height || 0) + 45) });
+
+            Doc.MakeMetadataFieldTemplate(fieldTemplate, Doc.GetProto(docTemplate), true);
+            Doc.ApplyTemplateTo(docTemplate, this.props.Document, undefined);
+            Doc.GetProto(this.dataDoc || this.props.Document).layoutCustom = Doc.MakeTitled("layoutCustom");
+        } else {
+            swapViews(this.props.Document, "layoutCustom", "layoutNative");
+        }
     }
 
     @undoBatch
@@ -487,9 +462,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     onDrop = (e: React.DragEvent) => {
         let text = e.dataTransfer.getData("text/plain");
         if (!e.isDefaultPrevented() && text && text.startsWith("<div")) {
-            let oldLayout = FieldValue(this.Document.layout) || "";
+            let oldLayout = StrCast(this.props.Document.layout);
             let layout = text.replace("{layout}", oldLayout);
-            this.Document.layout = layout;
+            this.props.Document.layout = layout;
             e.stopPropagation();
             e.preventDefault();
         }
@@ -527,9 +502,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         if (this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.DataDoc) {
             Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.ContainingCollectionView.props.DataDoc);
         } else {
-            if (this.Document.type !== DocumentType.COL && this.Document.type !== DocumentType.TEMPLATE) {
+            if (typeof this.props.Document.layout === "string") {
                 this.makeCustomViewClicked();
-            } else if (this.Document.nativeLayout) {
+            } else {
                 this.makeNativeViewClicked();
             }
         }
@@ -624,7 +599,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         }
         if (this.Document.type !== DocumentType.COL && this.Document.type !== DocumentType.TEMPLATE) {
             layoutItems.push({ description: "Use Custom Layout", event: this.makeCustomViewClicked, icon: "concierge-bell" });
-        } else if (this.props.Document.nativeLayout) {
+        } else if (this.props.Document.layoutNative) {
             layoutItems.push({ description: "Use Native Layout", event: this.makeNativeViewClicked, icon: "concierge-bell" });
         }
         !existing && cm.addItem({ description: "Layout...", subitems: layoutItems, icon: "compass" });
@@ -741,12 +716,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     chromeHeight = () => {
         let showOverlays = this.props.showOverlays ? this.props.showOverlays(this.layoutDoc) : undefined;
         let showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : StrCast(this.layoutDoc.showTitle);
-        let templates = Cast(this.layoutDoc.templates, listSpec("string"));
-        if (!showOverlays && templates instanceof List) {
-            templates.map(str => {
-                if (!showTitle && str.indexOf("{props.Document.title}") !== -1) showTitle = "title";
-            });
-        }
         return (showTitle ? 25 : 0) + 1;// bcz: why 8??
     }
 
@@ -843,66 +812,33 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     }
 }
 
+let swapViews = async (doc: any, newLayoutField: any, oldLayoutField: any) => {
+    let oldLayoutExt = await Cast(doc[oldLayoutField], Doc);
+    if (oldLayoutExt) {
+        oldLayoutExt.autoHeight = doc.autoHeight;
+        oldLayoutExt.width = doc.width;
+        oldLayoutExt.height = doc.height;
+        oldLayoutExt.nativeWidth = doc.nativeWidth;
+        oldLayoutExt.nativeHeight = doc.nativeHeight;
+        oldLayoutExt.ignoreAspect = doc.ignoreAspect;
+        oldLayoutExt.type = doc.type;
+        oldLayoutExt.layout = doc.layout;
+    }
 
-let makeNativeView = (doc: any): void => {
-    doc.layout = doc.nativeLayout;
-    doc.nativeLayout = undefined;
-    doc.type = doc.nativeType;
-
-    doc.customAutoHeight = doc.autoHeight;
-    doc.customWidth = doc.width;
-    doc.customHeight = doc.height;
-    doc.customNativeWidth = doc.nativeWidth;
-    doc.customNativeHeight = doc.nativeHeight;
-    doc.customIgnoreAspect = doc.ignoreAspect;
-
-    doc.autoHeight = doc.nonCustomAutoHeight;
-    doc.width = doc.nonCustomWidth;
-    doc.height = doc.nonCustomHeight;
-    doc.nativeWidth = doc.nonCustomNativeWidth;
-    doc.nativeHeight = doc.nonCustomNativeHeight;
-    doc.ignoreAspect = doc.nonCustomIgnoreAspect;
-    doc.nonCustomAutoHeight = undefined;
-    doc.nonCustomWidth = undefined;
-    doc.nonCustomHeight = undefined;
-    doc.nonCustomNativeWidth = undefined;
-    doc.nonCustomNativeHeight = undefined;
-    doc.nonCustomIgnoreAspect = undefined;
-};
-let makeCustomView = (doc: any): void => {
-    doc.nativeLayout = doc.layout;
-    doc.nativeType = doc.type;
-    doc.nonCustomAutoHeight = doc.autoHeight;
-    doc.nonCustomWidth = doc.nativeWidth;
-    doc.nonCustomHeight = doc.nativeHeight;
-    doc.nonCustomNativeWidth = doc.nativeWidth;
-    doc.nonCustomNativeHeight = doc.nativeHeight;
-    doc.nonCustomIgnoreAspect = doc.ignoreAspect;
-    let custom = doc.customLayout as Doc;
-    if (custom instanceof Doc) {
-        doc.type = DocumentType.TEMPLATE;
-        doc.layout = custom;
-        !custom.nativeWidth && (doc.nativeWidth = 0);
-        !custom.nativeHeight && (doc.nativeHeight = 0);
-        !custom.nativeWidth && (doc.ignoreAspect = true);
-        doc.autoHeight = doc.autoHeight;
-        doc.width = doc.customWidth;
-        doc.height = doc.customHeight;
-        doc.nativeWidth = doc.customNativeWidth;
-        doc.nativeHeight = doc.customNativeHeight;
-        doc.ignoreAspect = doc.ignoreAspect;
-        doc.customAutoHeight = undefined;
-        doc.customWidth = undefined;
-        doc.customHeight = undefined;
-        doc.customNativeWidth = undefined;
-        doc.customNativeHeight = undefined;
-        doc.customIgnoreAspect = undefined;
+    let newLayoutExt = newLayoutField && await Cast(doc[newLayoutField], Doc);
+    if (newLayoutExt) {
+        doc.autoHeight = newLayoutExt.autoHeight;
+        doc.width = newLayoutExt.width;
+        doc.height = newLayoutExt.height;
+        doc.nativeWidth = newLayoutExt.nativeWidth;
+        doc.nativeHeight = newLayoutExt.nativeHeight;
+        doc.ignoreAspect = newLayoutExt.ignoreAspect;
+        doc.type = newLayoutExt.type;
+        doc.layout = await newLayoutExt.layout;
     }
 };
+
 Scripting.addGlobal(function toggleDetail(doc: any) {
-    if (doc.type !== DocumentType.COL && doc.type !== DocumentType.TEMPLATE) {
-        makeCustomView(doc);
-    } else if (doc.nativeLayout) {
-        makeNativeView(doc);
-    }
+    let native = typeof doc.layout === "string";
+    swapViews(doc, native ? "layoutCustom" : "layoutNative", native ? "layoutNative" : "layoutCustom");
 });
\ No newline at end of file
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 0cf1208d7..ffa9a4e98 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -405,17 +405,21 @@ export namespace Doc {
         return docExtensionForField;
     }
 
-    export function UpdateDocumentExtensionForField(doc: Doc, fieldKey: string) {
+    export function UpdateDocumentExtensionForField(doc: Doc, fieldKey: string, immediate: boolean = false) {
         let docExtensionForField = doc[fieldKey + "_ext"] as Doc;
         if (docExtensionForField === undefined) {
-            setTimeout(() => {
-                CreateDocumentExtensionForField(doc, fieldKey);
-            }, 0);
+            if (immediate) CreateDocumentExtensionForField(doc, fieldKey);
+            else setTimeout(() => CreateDocumentExtensionForField(doc, fieldKey), 0);
         } else if (doc instanceof Doc) { // backward compatibility -- add fields for docs that don't have them already
             docExtensionForField.extendsDoc === undefined && setTimeout(() => docExtensionForField.extendsDoc = doc, 0);
             docExtensionForField.type === undefined && setTimeout(() => docExtensionForField.type = DocumentType.EXTENSION, 0);
         }
     }
+    export function MakeTitled(title: string) {
+        let doc = new Doc();
+        doc.title = title;
+        return doc;
+    }
     export function MakeAlias(doc: Doc) {
         let alias = !GetT(doc, "isPrototype", "boolean", true) ? Doc.MakeCopy(doc) : Doc.MakeDelegate(doc);
         if (alias.layout instanceof Doc) {
@@ -560,7 +564,7 @@ export namespace Doc {
         !templateDoc.nativeWidth && (otherdoc.ignoreAspect = true);
         return otherdoc;
     }
-    export function ApplyTemplateTo(templateDoc: Doc, target: Doc, targetData?: Doc, useTemplateDoc?: boolean) {
+    export function ApplyTemplateTo(templateDoc: Doc, target: Doc, targetData?: Doc) {
         if (!templateDoc) {
             target.layout = undefined;
             target.nativeWidth = undefined;
@@ -569,7 +573,7 @@ export namespace Doc {
             target.type = undefined;
             return;
         }
-        let temp = useTemplateDoc ? templateDoc : Doc.MakeDelegate(templateDoc);
+        let temp = Doc.MakeDelegate(templateDoc);
         target.nativeWidth = Doc.GetProto(target).nativeWidth = undefined;
         target.nativeHeight = Doc.GetProto(target).nativeHeight = undefined;
         !templateDoc.nativeWidth && (target.nativeWidth = 0);
-- 
cgit v1.2.3-70-g09d2

