From b33e45f1f839b3c6eaf1076e605abacd1bc6883c Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Thu, 29 Jul 2021 15:35:39 -0400
Subject: lots of updates!

---
 src/client/util/SettingsManager.tsx | 79 +++++++++++++++++++++++++++++++------
 1 file changed, 67 insertions(+), 12 deletions(-)

(limited to 'src/client/util/SettingsManager.tsx')

diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index 777394b05..3987497b8 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -18,6 +18,12 @@ const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
 
+export enum ColorScheme {
+    Dark = "Dark",
+    Light = "Light",
+    System = "Match System"
+}
+
 @observer
 export class SettingsManager extends React.Component<{}> {
     public static Instance: SettingsManager;
@@ -32,7 +38,7 @@ export class SettingsManager extends React.Component<{}> {
     @observable activeTab = "Accounts";
 
     @computed get backgroundColor() { return Doc.UserDoc().activeCollectionBackground; }
-
+    @computed get colorScheme() { return Doc.UserDoc().colorScheme; }
 
     constructor(props: {}) {
         super(props);
@@ -69,6 +75,28 @@ export class SettingsManager extends React.Component<{}> {
         else DocServer.Control.makeEditable();
     });
 
+    @undoBatch
+    @action
+    changeColorScheme = action((e: React.ChangeEvent) => {
+        const scheme: ColorScheme = (e.currentTarget as any).value;
+        switch (scheme) {
+            case ColorScheme.Light:
+                Doc.UserDoc().colorScheme = ColorScheme.Light;
+                addStyleSheetRule(SettingsManager._settingsStyle, "lm_header", { background: "#d3d3d3 !important" });
+                break;
+            case ColorScheme.Dark:
+                Doc.UserDoc().colorScheme = ColorScheme.Dark;
+                addStyleSheetRule(SettingsManager._settingsStyle, "lm_header", { background: "black !important" });
+                break;
+            case ColorScheme.System: default:
+                window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
+                    Doc.UserDoc().colorScheme = e.matches ? ColorScheme.Dark : ColorScheme.Light;
+                });
+                break;
+        }
+    });
+
+
     @computed get colorsContent() {
         const colorBox = (func: (color: ColorState) => void) => <SketchPicker onChange={func} color={StrCast(this.backgroundColor)}
             presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505',
@@ -90,8 +118,7 @@ export class SettingsManager extends React.Component<{}> {
             </Flyout>
         </div>;
 
-        const fontFamilies = ["Times New Roman", "Arial", "Georgia", "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"];
-        const fontSizes = ["7px", "8px", "9px", "10px", "12px", "14px", "16px", "18px", "20px", "24px", "32px", "48px", "72px"];
+        const colorSchemes = [ColorScheme.Light, ColorScheme.Dark, ColorScheme.System];
 
         return <div className="colors-content">
             <div className="preferences-color">
@@ -102,14 +129,11 @@ export class SettingsManager extends React.Component<{}> {
                 <div className="preferences-color-text">Border/Header Color</div>
                 {userColorFlyout}
             </div>
-            <div className="preferences-font">
-                <div className="preferences-font-text">Default Font</div>
-                <div className="preferences-font-controls">
-                    <select className="size-select" onChange={this.changeFontSize} value={StrCast(Doc.UserDoc().fontSize, "7px")}>
-                        {fontSizes.map(size => <option key={size} value={size} defaultValue={StrCast(Doc.UserDoc().fontSize)}> {size} </option>)}
-                    </select>
-                    <select className="font-select" onChange={this.changeFontFamily} value={StrCast(Doc.UserDoc().fontFamily, "Times New Roman")} >
-                        {fontFamilies.map(font => <option key={font} value={font} defaultValue={StrCast(Doc.UserDoc().fontFamily)}> {font} </option>)}
+            <div className="preferences-colorScheme">
+                <div className="preferences-color-text">Color Scheme</div>
+                <div className="preferences-color-controls">
+                    <select className="scheme-select" onChange={this.changeColorScheme} defaultValue={StrCast(Doc.UserDoc().colorScheme)}>
+                        {colorSchemes.map(scheme => <option key={scheme} value={scheme}> {scheme} </option>)}
                     </select>
                 </div>
             </div>
@@ -132,6 +156,16 @@ export class SettingsManager extends React.Component<{}> {
                     checked={BoolCast(Doc.UserDoc()._raiseWhenDragged)} />
                 <div className="preferences-check">Raise on drag</div>
             </div>
+            <div>
+                <input type="checkbox" onChange={e => Doc.UserDoc()._showLabel = !Doc.UserDoc()._showLabel}
+                    checked={BoolCast(Doc.UserDoc()._showLabel)} />
+                <div className="preferences-check">Show tool button labels</div>
+            </div>
+            <div>
+                <input type="checkbox" onChange={e => Doc.UserDoc()._showMenuLabel = !Doc.UserDoc()._showMenuLabel}
+                    checked={BoolCast(Doc.UserDoc()._showMenuLabel)} />
+                <div className="preferences-check">Show menu button labels</div>
+            </div>
         </div>;
     }
 
@@ -149,6 +183,27 @@ export class SettingsManager extends React.Component<{}> {
         </div>;
     }
 
+    @computed get textContent() {
+
+        const fontFamilies = ["Times New Roman", "Arial", "Georgia", "Comic Sans MS", "Tahoma", "Impact", "Crimson Text", "Roboto"];
+        const fontSizes = ["7px", "8px", "9px", "10px", "12px", "14px", "16px", "18px", "20px", "24px", "32px", "48px", "72px"];
+
+        return (
+            <div className="tab-content appearances-content">
+                <div className="preferences-font">
+                    <div className="preferences-font-text">Default Font</div>
+                    <div className="preferences-font-controls">
+                        <select className="size-select" onChange={this.changeFontSize} value={StrCast(Doc.UserDoc().fontSize, "7px")}>
+                            {fontSizes.map(size => <option key={size} value={size} defaultValue={StrCast(Doc.UserDoc().fontSize)}> {size} </option>)}
+                        </select>
+                        <select className="font-select" onChange={this.changeFontFamily} value={StrCast(Doc.UserDoc().fontFamily, "Times New Roman")} >
+                            {fontFamilies.map(font => <option key={font} value={font} defaultValue={StrCast(Doc.UserDoc().fontFamily)}> {font} </option>)}
+                        </select>
+                    </div>
+                </div>
+            </div>);
+    }
+
     @action
     changeVal = (e: React.ChangeEvent, pass: string) => {
         const value = (e.target as any).value;
@@ -228,7 +283,7 @@ export class SettingsManager extends React.Component<{}> {
         // { title: "Accounts", ele: this.accountsContent }, { title: "Preferences", ele: this.preferencesContent }];
 
         const tabs = [{ title: "Accounts", ele: this.accountsContent }, { title: "Modes", ele: this.modesContent },
-        { title: "Appearance", ele: this.appearanceContent }];
+        { title: "Appearance", ele: this.appearanceContent }, { title: "Text", ele: this.textContent }];
 
         return <div className="settings-interface">
             <div className="settings-panel">
-- 
cgit v1.2.3-70-g09d2


From 81ae5175aebf7e14a781a73d4a7cbaec0b8f3e4a Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 9 Aug 2021 14:26:14 -0400
Subject: fixed augment only text to resize correctly with autoheight. fixed
 acls to cache correctly for new documents. fixed links to be shared across
 users.  fixed links to always default to public.

---
 src/client/DocServer.ts                            |  2 +-
 src/client/documents/Documents.ts                  |  8 ++-
 src/client/util/CurrentUserUtils.ts                | 16 +++---
 src/client/util/LinkManager.ts                     | 67 ++++++++++++++--------
 src/client/util/SettingsManager.tsx                |  3 +-
 src/client/util/SharingManager.tsx                 |  4 +-
 src/client/views/MainView.tsx                      |  2 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx | 20 ++++---
 src/fields/util.ts                                 |  4 +-
 9 files changed, 79 insertions(+), 47 deletions(-)

(limited to 'src/client/util/SettingsManager.tsx')

diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts
index 5712a1d64..f4e3a22cf 100644
--- a/src/client/DocServer.ts
+++ b/src/client/DocServer.ts
@@ -1,6 +1,6 @@
 import * as io from 'socket.io-client';
 import { MessageStore, YoutubeQueryTypes, GestureContent, MobileInkOverlayContent, UpdateMobileInkOverlayPositionContent, MobileDocumentUploadContent } from "./../server/Message";
-import { Opt, Doc, UpdatingFromServer } from '../fields/Doc';
+import { Opt, Doc, UpdatingFromServer, updateCachedAcls } from '../fields/Doc';
 import { Utils, emptyFunction } from '../Utils';
 import { SerializationHelper } from './util/SerializationHelper';
 import { RefField } from '../fields/RefField';
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 93f0880a4..48886aa3b 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -1,7 +1,7 @@
 import { action, runInAction } from "mobx";
 import { basename, extname } from "path";
 import { DateField } from "../../fields/DateField";
-import { Doc, DocListCast, DocListCastAsync, Field, HeightSym, Opt, WidthSym, Initializing } from "../../fields/Doc";
+import { Doc, DocListCast, DocListCastAsync, Field, HeightSym, Opt, WidthSym, Initializing, updateCachedAcls } from "../../fields/Doc";
 import { Id } from "../../fields/FieldSymbols";
 import { HtmlField } from "../../fields/HtmlField";
 import { InkField } from "../../fields/InkField";
@@ -577,7 +577,7 @@ export namespace Docs {
             dataProps.creationDate = new DateField;
             dataProps[`${fieldKey}-lastModified`] = new DateField;
             dataProps["acl-Override"] = "None";
-            dataProps["acl-Public"] = Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment;
+            dataProps["acl-Public"] = options["acl-Public"] ? options["acl-Public"] : Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment;
 
             dataProps[fieldKey] = data;
 
@@ -588,13 +588,15 @@ export namespace Docs {
 
             viewProps.author = Doc.CurrentUserEmail;
             viewProps["acl-Override"] = "None";
-            viewProps["acl-Public"] = Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment;
+            viewProps["acl-Public"] = options["_acl-Public"] ? options["_acl-Public"] : Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment;
             const viewDoc = Doc.assign(Doc.MakeDelegate(dataDoc, delegId), viewProps, true, true);
             ![DocumentType.LINK, DocumentType.MARKER, DocumentType.LABEL].includes(viewDoc.type as any) && DocUtils.MakeLinkToActiveAudio(() => viewDoc);
 
             !Doc.IsSystem(dataDoc) && ![DocumentType.MARKER, DocumentType.KVP, DocumentType.LINK, DocumentType.LINKANCHOR].includes(proto.type as any) &&
                 !dataDoc.isFolder && !dataProps.annotationOn && Doc.AddDocToList(Cast(Doc.UserDoc().myFileOrphans, Doc, null), "data", dataDoc);
 
+            updateCachedAcls(dataDoc);
+            updateCachedAcls(viewDoc);
             return viewDoc;
         }
 
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 14c43fb1c..34990e121 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -2,13 +2,14 @@ import { computed, observable, reaction } from "mobx";
 import * as rp from 'request-promise';
 import { DataSym, Doc, DocListCast, DocListCastAsync } from "../../fields/Doc";
 import { Id } from "../../fields/FieldSymbols";
+import { InkTool } from "../../fields/InkField";
 import { List } from "../../fields/List";
 import { PrefetchProxy } from "../../fields/Proxy";
 import { RichTextField } from "../../fields/RichTextField";
 import { listSpec } from "../../fields/Schema";
 import { SchemaHeaderField } from "../../fields/SchemaHeaderField";
 import { ComputedField, ScriptField } from "../../fields/ScriptField";
-import { BoolCast, Cast, NumCast, PromiseValue, StrCast, DateCast } from "../../fields/Types";
+import { BoolCast, Cast, DateCast, NumCast, PromiseValue, StrCast } from "../../fields/Types";
 import { nullAudio } from "../../fields/URLField";
 import { SharingPermissions } from "../../fields/util";
 import { Utils } from "../../Utils";
@@ -19,6 +20,7 @@ import { Networking } from "../Network";
 import { CollectionDockingView } from "../views/collections/CollectionDockingView";
 import { DimUnit } from "../views/collections/collectionMulticolumn/CollectionMulticolumnView";
 import { CollectionView, CollectionViewType } from "../views/collections/CollectionView";
+import { Colors } from "../views/global/globalEnums";
 import { MainView } from "../views/MainView";
 import { FormattedTextBox } from "../views/nodes/formattedText/FormattedTextBox";
 import { LabelBox } from "../views/nodes/LabelBox";
@@ -31,13 +33,10 @@ import { LinkManager } from "./LinkManager";
 import { Scripting } from "./Scripting";
 import { SearchUtil } from "./SearchUtil";
 import { SelectionManager } from "./SelectionManager";
-import { UndoManager } from "./UndoManager";
-import { SnappingManager } from "./SnappingManager";
-import { InkTool } from "../../fields/InkField";
-import { SharingManager } from "./SharingManager";
-import { computedFn } from "mobx-utils";
 import { ColorScheme } from "./SettingsManager";
-import { Colors } from "../views/global/globalEnums";
+import { SharingManager } from "./SharingManager";
+import { SnappingManager } from "./SnappingManager";
+import { UndoManager } from "./UndoManager";
 
 
 export let resolvedPorts: { server: number, socket: number };
@@ -915,6 +914,7 @@ export class CurrentUserUtils {
             let linkDocs = Docs.newAccount ? undefined : await DocServer.GetRefField(linkDatabaseId);
             if (!linkDocs) {
                 linkDocs = new Doc(linkDatabaseId, true);
+                (linkDocs as Doc).title = "LINK DATABASE: " + Doc.CurrentUserEmail;
                 (linkDocs as Doc).author = Doc.CurrentUserEmail;
                 (linkDocs as Doc).data = new List<Doc>([]);
                 (linkDocs as Doc)["acl-Public"] = SharingPermissions.Augment;
@@ -1029,7 +1029,7 @@ export class CurrentUserUtils {
         doc.fontFamily = StrCast(doc.fontFamily, "Arial");
         doc.fontColor = StrCast(doc.fontColor, "black");
         doc.fontHighlight = StrCast(doc.fontHighlight, "");
-        doc.defaultAclPrivate = BoolCast(doc.defaultAclPrivate, true);
+        doc.defaultAclPrivate = BoolCast(doc.defaultAclPrivate, false);
         doc.activeCollectionBackground = StrCast(doc.activeCollectionBackground, "white");
         doc.activeCollectionNestedBackground = Cast(doc.activeCollectionNestedBackground, "string", null);
         doc.noviceMode = BoolCast(doc.noviceMode, true);
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index 8abfd740c..933b98a8c 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -1,4 +1,4 @@
-import { observable, observe, action } from "mobx";
+import { observable, observe, action, reaction, computed } from "mobx";
 import { computedFn } from "mobx-utils";
 import { DirectLinksSym, Doc, DocListCast, Field, Opt } from "../../fields/Doc";
 import { List } from "../../fields/List";
@@ -26,36 +26,41 @@ type CreateViewFunc = (doc: Doc, followLinkLocation: string, finished?: () => vo
 export class LinkManager {
 
     @observable static _instance: LinkManager;
-    @observable static userDocs: Doc[] = [];
+    @observable static userLinkDBs: Doc[] = [];
     public static currentLink: Opt<Doc>;
     public static get Instance() { return LinkManager._instance; }
+    public static addLinkDB = (linkDb: any) => LinkManager.userLinkDBs.push(linkDb);
+    static links: Doc[] = [];
     constructor() {
         LinkManager._instance = this;
         setTimeout(() => {
-            LinkManager.userDocs = [Doc.LinkDBDoc().data as Doc, ...SharingManager.Instance.users.map(user => user.linkDatabase)];
-            const addLinkToDoc = action((link: Doc): any => {
+            LinkManager.userLinkDBs = [];
+            const addLinkToDoc = (link: Doc) => {
                 const a1 = link?.anchor1;
                 const a2 = link?.anchor2;
-                if (a1 instanceof Promise || a2 instanceof Promise) return PromiseValue(a1).then(a1 => PromiseValue(a2).then(a2 => addLinkToDoc(link)));
-                if (a1 instanceof Doc && a2 instanceof Doc && ((a1.author !== undefined && a2.author !== undefined) || link.author === Doc.CurrentUserEmail)) {
-                    Doc.GetProto(a1)[DirectLinksSym].add(link);
-                    Doc.GetProto(a2)[DirectLinksSym].add(link);
-                    Doc.GetProto(link)[DirectLinksSym].add(link);
-                }
-            });
-            const remLinkFromDoc = action((link: Doc): any => {
+                Promise.all([a1, a2]).then(action(() => {
+                    if (a1 instanceof Doc && a2 instanceof Doc && ((a1.author !== undefined && a2.author !== undefined) || link.author === Doc.CurrentUserEmail)) {
+                        Doc.GetProto(a1)[DirectLinksSym].add(link);
+                        Doc.GetProto(a2)[DirectLinksSym].add(link);
+                        Doc.GetProto(link)[DirectLinksSym].add(link);
+                    }
+                }));
+            }
+            const remLinkFromDoc = (link: Doc) => {
                 const a1 = link?.anchor1;
                 const a2 = link?.anchor2;
-                if (a1 instanceof Promise || a2 instanceof Promise) return PromiseValue(a1).then(a1 => PromiseValue(a2).then(a2 => remLinkFromDoc(link)));
-                if (a1 instanceof Doc && a2 instanceof Doc && ((a1.author !== undefined && a2.author !== undefined) || link.author === Doc.CurrentUserEmail)) {
-                    Doc.GetProto(a1)[DirectLinksSym].delete(link);
-                    Doc.GetProto(a2)[DirectLinksSym].delete(link);
-                    Doc.GetProto(link)[DirectLinksSym].delete(link);
-                }
-            });
-            const watchUserLinks = (userLinks: List<Doc>) => {
+                Promise.all([a1, a2]).then(action(() => {
+                    if (a1 instanceof Doc && a2 instanceof Doc && ((a1.author !== undefined && a2.author !== undefined) || link.author === Doc.CurrentUserEmail)) {
+                        Doc.GetProto(a1)[DirectLinksSym].delete(link);
+                        Doc.GetProto(a2)[DirectLinksSym].delete(link);
+                        Doc.GetProto(link)[DirectLinksSym].delete(link);
+                    }
+                }));
+            }
+            const watchUserLinkDB = (userLinkDBDoc: Doc) => {
+                LinkManager.links.push(...DocListCast(userLinkDBDoc.data));
                 const toRealField = (field: Field) => field instanceof ProxyField ? field.value() : field;  // see List.ts.  data structure is not a simple list of Docs, but a list of ProxyField/Fields
-                observe(userLinks, change => {
+                observe(userLinkDBDoc.data as Doc, change => {  // observe pushes/splices on a user link DB 'data' field (should only happen for local changes)
                     switch (change.type as any) {
                         case "splice":
                             (change as any).added.forEach((link: any) => addLinkToDoc(toRealField(link)));
@@ -64,13 +69,29 @@ export class LinkManager {
                         case "update": //let oldValue = change.oldValue;
                     }
                 }, true);
+                observe(userLinkDBDoc, "data",  // obsever when a new array of links is assigned as the link DB 'data' field (should happen whenever a remote user adds/removes a link)
+                    change => {
+                        switch (change.type as any) {
+                            case "update":
+                                Promise.all([...(change.oldValue as any as Doc[] || []), ...(change.newValue as any as Doc[] || [])]).then(doclist => {
+                                    const oldDocs = doclist.slice(0, (change.oldValue as any as Doc[] || []).length);
+                                    const newDocs = doclist.slice((change.oldValue as any as Doc[] || []).length, doclist.length);
+
+                                    const added = newDocs?.filter(link => !(oldDocs || []).includes(link));
+                                    const removed = oldDocs?.filter(link => !(newDocs || []).includes(link));
+                                    added?.forEach((link: any) => addLinkToDoc(toRealField(link)));
+                                    removed?.forEach((link: any) => remLinkFromDoc(toRealField(link)));
+                                });
+                        }
+                    }, true);
             };
-            observe(LinkManager.userDocs, change => {
+            observe(LinkManager.userLinkDBs, change => {
                 switch (change.type as any) {
-                    case "splice": (change as any).added.forEach(watchUserLinks); break;
+                    case "splice": (change as any).added.forEach(watchUserLinkDB); break;
                     case "update": //let oldValue = change.oldValue;
                 }
             }, true);
+            LinkManager.addLinkDB(Doc.LinkDBDoc());
         });
     }
 
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index 3987497b8..bd91db779 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -268,7 +268,8 @@ export class SettingsManager extends React.Component<{}> {
                 <div className="tab-column-content">
                     <button onClick={() => GroupManager.Instance?.open()}>Manage groups</button>
                     <div className="default-acl">
-                        <input className="acl-check" type="checkbox" checked={BoolCast(Doc.UserDoc()?.defaultAclPrivate)} onChange={action(() => Doc.UserDoc().defaultAclPrivate = !Doc.UserDoc().defaultAclPrivate)} />
+                        <input className="acl-check" type="checkbox" checked={BoolCast(Doc.UserDoc()?.defaultAclPrivate)}
+                            onChange={action(() => Doc.UserDoc().defaultAclPrivate = !Doc.UserDoc().defaultAclPrivate)} />
                         <div className="acl-text">Default access private</div>
                     </div>
                 </div>
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index a8972b988..6c4556250 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -23,6 +23,7 @@ import { GroupManager, UserOptions } from "./GroupManager";
 import { GroupMemberView } from "./GroupMemberView";
 import { SelectionManager } from "./SelectionManager";
 import "./SharingManager.scss";
+import { LinkManager } from "./LinkManager";
 
 export interface User {
     email: string;
@@ -154,10 +155,11 @@ export class SharingManager extends React.Component<{}> {
                 }
             });
             return Promise.all(evaluating).then(() => {
-                runInAction(() => {
+                runInAction(async () => {
                     for (const sharer of sharingDocs) {
                         if (!this.users.find(user => user.user.email === sharer.user.email)) {
                             this.users.push(sharer);
+                            LinkManager.addLinkDB(sharer.linkDatabase);
                         }
                     }
                 });
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 2be3c3135..3d7446cbe 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -108,7 +108,7 @@ export class MainView extends React.Component {
         this._sidebarContent.proto = undefined;
         if (!MainView.Live) {
             DocServer.setPlaygroundFields(["dataTransition", "autoHeight", "showSidebar", "sidebarWidthPercent", "viewTransition",
-                "panX", "panY", "width", "height", "nativeWidth", "nativeHeight",
+                "panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "text-scrollHeight", "text-height",
                 "viewScale", "scrollTop", "hidden", "curPage", "viewType", "chromeHidden", "nativeWidth"]); // can play with these fields on someone else's
         }
         DocServer.GetRefField("rtfProto").then(proto => (proto instanceof Doc) && reaction(() => StrCast(proto.BROADCAST_MESSAGE), msg => msg && alert(msg)));
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index f7bed2fa1..9bba15b28 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -431,6 +431,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         this.ProseRef = ele;
         this._dropDisposer?.();
         ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.layoutDoc));
+        // if (this.autoHeight) this.tryUpdateScrollHeight(); 
     }
 
     @undoBatch
@@ -1438,16 +1439,19 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             }
         }
     }
-    tryUpdateScrollHeight() {
+    tryUpdateScrollHeight = () => {
         if (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this.props.docViewPath())) {
             const margins = 2 * NumCast(this.layoutDoc._yMargin, this.props.yPadding || 0);
-            const proseHeight = !this.ProseRef ? 0 : Array.from(this.ProseRef.children[0].children).reduce((p, child) => p + Number(getComputedStyle(child).height.replace("px", "")), margins);
-            const scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.docMaxAutoHeight, proseHeight), proseHeight);
-            if (scrollHeight && this.props.renderDepth && !this.props.dontRegisterView) {  // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation
-                const setScrollHeight = () => this.rootDoc[this.fieldKey + "-scrollHeight"] = scrollHeight;
-                if (this.rootDoc === this.layoutDoc.doc || this.layoutDoc.resolvedDataDoc) {
-                    setScrollHeight();
-                } else setTimeout(setScrollHeight, 10); // if we have a template that hasn't been resolved yet, we can't set the height or we'd be setting it on the unresolved template.  So set a timeout and hope its arrived...
+            const children = this.ProseRef?.children.length ? Array.from(this.ProseRef.children[0].children) : undefined;
+            if (children) {
+                const proseHeight = !this.ProseRef ? 0 : children.reduce((p, child) => p + Number(getComputedStyle(child).height.replace("px", "")), margins);
+                const scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.docMaxAutoHeight, proseHeight), proseHeight);
+                if (scrollHeight && this.props.renderDepth && !this.props.dontRegisterView) {  // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation
+                    const setScrollHeight = () => this.rootDoc[this.fieldKey + "-scrollHeight"] = scrollHeight;
+                    if (this.rootDoc === this.layoutDoc.doc || this.layoutDoc.resolvedDataDoc) {
+                        setScrollHeight();
+                    } else setTimeout(setScrollHeight, 10); // if we have a template that hasn't been resolved yet, we can't set the height or we'd be setting it on the unresolved template.  So set a timeout and hope its arrived...
+                }
             }
         }
     }
diff --git a/src/fields/util.ts b/src/fields/util.ts
index 2bb6b45c2..439c4d333 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -141,7 +141,9 @@ export function denormalizeEmail(email: string) {
 export function inheritParentAcls(parent: Doc, child: Doc) {
     const dataDoc = parent[DataSym];
     for (const key of Object.keys(dataDoc)) {
-        key.startsWith("acl") && distributeAcls(key, dataDoc[key], child);
+        // if the default acl mode is private, then don't inherit the acl-Public permission, but set it to private.
+        const permission = (key === "acl-Public" && Doc.UserDoc().defaultAclPrivate) ? AclPrivate : dataDoc[key];
+        key.startsWith("acl") && distributeAcls(key, permission, child);
     }
 }
 
-- 
cgit v1.2.3-70-g09d2

