From 36630b9aa2e1c4710a69a4fdf4ec98c3f5bca92c Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 21 Aug 2020 16:05:52 -0400
Subject: trying scenes instead of workspaces

---
 src/client/views/nodes/formattedText/DashDocView.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx
index 145ee8c2e..0e965ba9a 100644
--- a/src/client/views/nodes/formattedText/DashDocView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocView.tsx
@@ -175,7 +175,7 @@ export class DashDocView extends React.Component<IDashDocView> {
         const outerStyle = {
             position: "relative" as "relative",
             textIndent: "0",
-            border: "1px solid " + StrCast(this._textBox.Document.color, (Cast(Doc.UserDoc().activeWorkspace, Doc, null).darkScheme ? "dimGray" : "lightGray")),
+            border: "1px solid " + StrCast(this._textBox.Document.color, (Cast(Doc.UserDoc().activeScene, Doc, null).darkScheme ? "dimGray" : "lightGray")),
             width: this.props.node.props.width,
             height: this.props.node.props.height,
             display: this.props.node.props.hidden ? "none" : "inline-block",
@@ -202,7 +202,7 @@ export class DashDocView extends React.Component<IDashDocView> {
                 ({ dim, color }) => {
                     spanStyle.width = outerStyle.width = Math.max(20, dim[0]) + "px";
                     spanStyle.height = outerStyle.height = Math.max(20, dim[1]) + "px";
-                    outerStyle.border = "1px solid " + StrCast(finalLayout.color, (Cast(Doc.UserDoc().activeWorkspace, Doc, null).darkScheme ? "dimGray" : "lightGray"));
+                    outerStyle.border = "1px solid " + StrCast(finalLayout.color, (Cast(Doc.UserDoc().activeScene, Doc, null).darkScheme ? "dimGray" : "lightGray"));
                 }, { fireImmediately: true });
 
             if (node.attrs.width !== dashDoc._width + "px" || node.attrs.height !== dashDoc._height + "px") {
-- 
cgit v1.2.3-70-g09d2


From ca9cf672bdfd8ebf11cb20264474bcb9d9729944 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 21 Aug 2020 18:46:58 -0400
Subject: switched from "scenes" to "dashboards"

---
 src/client/documents/Documents.ts                  |  4 +-
 src/client/util/CurrentUserUtils.ts                | 40 ++++++-------
 src/client/util/History.ts                         |  2 +-
 src/client/util/SettingsManager.tsx                |  2 +-
 src/client/views/DocumentDecorations.tsx           |  2 +-
 src/client/views/MainView.scss                     |  2 +-
 src/client/views/MainView.tsx                      | 50 ++++++++--------
 .../views/collections/CollectionDockingView.tsx    | 35 ++++++-----
 .../views/collections/CollectionTreeView.tsx       |  8 +--
 src/client/views/collections/CollectionView.tsx    |  2 +-
 .../CollectionFreeFormLayoutEngines.tsx            |  2 +-
 src/client/views/nodes/DocumentView.tsx            |  8 +--
 .../views/nodes/formattedText/DashDocView.tsx      |  4 +-
 .../views/nodes/formattedText/RichTextSchema.tsx   |  4 +-
 src/mobile/MobileInterface.tsx                     | 70 +++++++++++-----------
 15 files changed, 120 insertions(+), 115 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 7d114d417..697ff858f 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -820,7 +820,9 @@ 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), { ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id);
-            Doc.GetProto(inst).data = new List<Doc>(documents);
+            const tabs = TreeDocument(documents, { title: "Active Tabs" });
+            const all = TreeDocument([], { title: "Other Tabs" });
+            Doc.GetProto(inst).data = new List<Doc>([tabs, all]);
             return inst;
         }
 
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 4b1c48bd3..b439b8b43 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -36,7 +36,7 @@ export class CurrentUserUtils {
     @computed public static get UserDocument() { return Doc.UserDoc(); }
 
     @observable public static GuestTarget: Doc | undefined;
-    @observable public static GuestScene: Doc | undefined;
+    @observable public static GuestDashboard: Doc | undefined;
     @observable public static GuestMobile: Doc | undefined;
 
     @observable public static propertiesWidth: number = 0;
@@ -510,11 +510,11 @@ export class CurrentUserUtils {
     }[] {
         this.setupSharingSidebar(doc);  // sets up the right sidebar collection for mobile upload documents and sharing
         return [
-            { title: "Sharing", target: Cast(doc["sidebar-sharing"], Doc, null), icon: "users", click: 'selectMainMenu(self)', watchedDocuments: doc["sidebar-sharing"] as Doc },
-            { title: "Scenes", target: Cast(doc["sidebar-scenes"], Doc, null), icon: "desktop", click: 'selectMainMenu(self)' },
+            { title: "Dashboards", target: Cast(doc["sidebar-dashboards"], Doc, null), icon: "desktop", click: 'selectMainMenu(self)' },
             { title: "Catalog", target: undefined as any, icon: "file", click: 'selectMainMenu(self)' },
             { title: "Archive", target: Cast(doc["sidebar-recentlyClosed"], Doc, null), icon: "archive", click: 'selectMainMenu(self)' },
             { title: "Import", target: Cast(doc["sidebar-import"], Doc, null), icon: "upload", click: 'selectMainMenu(self)' },
+            { title: "Sharing", target: Cast(doc["sidebar-sharing"], Doc, null), icon: "users", click: 'selectMainMenu(self)', watchedDocuments: doc["sidebar-sharing"] as Doc },
             { title: "Tools", target: Cast(doc["sidebar-tools"], Doc, null), icon: "wrench", click: 'selectMainMenu(self)' },
             { title: "Help", target: undefined as any, icon: "question-circle", click: 'selectMainMenu(self)' },
             { title: "Settings", target: undefined as any, icon: "cog", click: 'selectMainMenu(self)' },
@@ -592,7 +592,7 @@ export class CurrentUserUtils {
     // SEts up mobile buttons for inside mobile menu
     static setupMobileButtons(doc?: Doc, buttons?: string[]) {
         const docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, ischecked?: string, activePen?: Doc, backgroundColor?: string, info: string, dragFactory?: Doc }[] = [
-            { title: "SCENES", icon: "bars", click: 'switchToMobileLibrary()', backgroundColor: "lightgrey", info: "Access your Scenes from your mobile, and navigate through all of your documents. " },
+            { title: "SCENES", icon: "bars", click: 'switchToMobileLibrary()', backgroundColor: "lightgrey", info: "Access your Dashboards from your mobile, and navigate through all of your documents. " },
             { title: "UPLOAD", icon: "upload", click: 'openMobileUploads()', backgroundColor: "lightgrey", info: "Upload files from your mobile device so they can be accessed on Dash Web." },
             { title: "MOBILE UPLOAD", icon: "mobile", click: 'switchToMobileUploadCollection()', backgroundColor: "lightgrey", info: "Access the collection of your mobile uploads." },
             { title: "RECORD", icon: "microphone", click: 'openMobileAudio()', backgroundColor: "lightgrey", info: "Use your phone to record, dictate and then upload audio onto Dash Web." },
@@ -689,7 +689,7 @@ export class CurrentUserUtils {
     }
 
     static setupLibrary(userDoc: Doc) {
-        return CurrentUserUtils.setupScenes(userDoc);
+        return CurrentUserUtils.setupDashboards(userDoc);
     }
 
     // setup the Creator button which will display the creator panel.  This panel will include the drag creators and the color picker. 
@@ -724,28 +724,28 @@ export class CurrentUserUtils {
         }
     }
 
-    static async setupScenes(doc: Doc) {
-        // setup scenes library item
-        await doc.myScenes;
-        if (doc.myScenes === undefined) {
-            doc.myScenes = new PrefetchProxy(Docs.Create.TreeDocument([], {
+    static async setupDashboards(doc: Doc) {
+        // setup dashboards library item
+        await doc.myDashboards;
+        if (doc.myDashboards === undefined) {
+            doc.myDashboards = new PrefetchProxy(Docs.Create.TreeDocument([], {
                 title: "SCENES", _height: 100, forceActive: true, boxShadow: "0 0", lockedPosition: true, treeViewOpen: true, system: true
             }));
         }
-        if (doc["sidebar-scenes"] === undefined) {
-            const newScene = ScriptField.MakeScript(`createNewScene()`);
-            (doc.myScenes as Doc).contextMenuScripts = new List<ScriptField>([newScene!]);
-            (doc.myScenes as Doc).contextMenuLabels = new List<string>(["Create New Scene"]);
+        if (doc["sidebar-dashboards"] === undefined) {
+            const newDashboard = ScriptField.MakeScript(`createNewDashboard()`);
+            (doc.myDashboards as Doc).contextMenuScripts = new List<ScriptField>([newDashboard!]);
+            (doc.myDashboards as Doc).contextMenuLabels = new List<string>(["Create New Dashboard"]);
 
-            const scenes = doc.myScenes as Doc;
+            const dashboards = doc.myDashboards as Doc;
 
-            doc["sidebar-scenes"] = new PrefetchProxy(Docs.Create.TreeDocument([scenes], {
+            doc["sidebar-dashboards"] = new PrefetchProxy(Docs.Create.TreeDocument([dashboards], {
                 treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias",
                 treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, treeViewOpen: true,
                 lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true
             })) as any as Doc;
         }
-        return doc.myScenes as any as Doc;
+        return doc.myDashboards as any as Doc;
     }
 
     static setupCatalog(doc: Doc) {
@@ -821,7 +821,7 @@ export class CurrentUserUtils {
     static async setupSidebarButtons(doc: Doc) {
         CurrentUserUtils.setupSidebarContainer(doc);
         await CurrentUserUtils.setupToolsBtnPanel(doc);
-        CurrentUserUtils.setupScenes(doc);
+        CurrentUserUtils.setupDashboards(doc);
         CurrentUserUtils.setupCatalog(doc);
         CurrentUserUtils.setupRecentlyClosed(doc);
         CurrentUserUtils.setupUserDoc(doc);
@@ -1002,8 +1002,8 @@ export class CurrentUserUtils {
     }
 }
 
-Scripting.addGlobal(function createNewScene() { return MainView.Instance.createNewScene(); },
-    "creates a new scene when called");
+Scripting.addGlobal(function createNewDashboard() { return MainView.Instance.createNewDashboard(); },
+    "creates a new dashboard when called");
 
 Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); },
     "returns all the links to the document or its annotations", "(doc: any)");
diff --git a/src/client/util/History.ts b/src/client/util/History.ts
index aed887055..cab682ac7 100644
--- a/src/client/util/History.ts
+++ b/src/client/util/History.ts
@@ -197,7 +197,7 @@ export namespace HistoryUtil {
             await Promise.all(Object.keys(init).map(id => initDoc(id, init[id])));
         }
         if (field instanceof Doc) {
-            MainView.Instance.openScene(field, true);
+            MainView.Instance.openDashboard(field, true);
         }
     }
 
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index b2131c9b2..accb9c346 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -158,7 +158,7 @@ export default class SettingsManager extends React.Component<{}> {
                 <div className="settings-title">Settings</div>
                 <div className="settings-username">{Doc.CurrentUserEmail}</div>
                 <button className="logout-button" onClick={() => window.location.assign(Utils.prepend("/logout"))} >
-                    {CurrentUserUtils.GuestScene ? "Exit" : "Log Out"}
+                    {CurrentUserUtils.GuestDashboard ? "Exit" : "Log Out"}
                 </button>
                 <div className="close-button" onClick={this.close}>
                     <FontAwesomeIcon icon={fa.faTimes} color="black" size={"lg"} />
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index fdce8bf71..c44c2968c 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -596,7 +596,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         return <FontAwesomeIcon icon={button} className="documentView-minimizedIcon" />;
     }
     render() {
-        const darkScheme = Cast(Doc.UserDoc().activeScene, Doc, null)?.darkScheme ? "dimgray" : undefined;
+        const darkScheme = Cast(Doc.UserDoc().activeDashboard, Doc, null)?.darkScheme ? "dimgray" : undefined;
         const bounds = this.Bounds;
         const seldoc = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined;
         if (SnappingManager.GetIsDragging() || bounds.r - bounds.x < 1 || bounds.x === Number.MAX_VALUE || !seldoc || this._hidden || isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) {
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index fb80bfc0d..2d742f4ba 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -313,7 +313,7 @@
 
 }
 
-.mainView-scene {
+.mainView-dashboard {
     height: 200px;
     position: relative;
     display: flex;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 08ac69a38..64efc5ee5 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -77,10 +77,10 @@ export class MainView extends React.Component {
     @observable private _panelHeight: number = 0;
     @observable private _flyoutTranslate: boolean = false;
     @observable public flyoutWidth: number = 0;
-    private get darkScheme() { return BoolCast(Cast(this.userDoc?.activeScene, Doc, null)?.darkScheme); }
+    private get darkScheme() { return BoolCast(Cast(this.userDoc?.activeDashboard, Doc, null)?.darkScheme); }
 
     @computed private get userDoc() { return Doc.UserDoc(); }
-    @computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeScene, Doc)) : CurrentUserUtils.GuestScene; }
+    @computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeDashboard, Doc)) : CurrentUserUtils.GuestDashboard; }
     @computed public get mainFreeform(): Opt<Doc> { return (docs => (docs && docs.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); }
     @computed public get searchDoc() { return Cast(this.userDoc["search-panel"], Doc) as Doc; }
 
@@ -224,12 +224,12 @@ export class MainView extends React.Component {
     }
 
     initAuthenticationRouters = async () => {
-        // Load the user's active scene, or create a new one if initial session after signup
+        // Load the user's active dashboard, or create a new one if initial session after signup
         const received = CurrentUserUtils.MainDocId;
         if (received && !this.userDoc) {
             reaction(
                 () => CurrentUserUtils.GuestTarget,
-                target => target && this.createNewScene(),
+                target => target && this.createNewDashboard(),
                 { fireImmediately: true }
             );
         } else {
@@ -242,21 +242,21 @@ export class MainView extends React.Component {
                     }),
                 );
             }
-            const doc = this.userDoc && await Cast(this.userDoc.activeScene, Doc);
+            const doc = this.userDoc && await Cast(this.userDoc.activeDashboard, Doc);
             if (doc) {
-                this.openScene(doc);
+                this.openDashboard(doc);
             } else {
-                this.createNewScene();
+                this.createNewDashboard();
             }
         }
     }
 
     @action
-    createNewScene = async (id?: string) => {
+    createNewDashboard = async (id?: string) => {
         const myCatalog = Doc.UserDoc().myCatalog as Doc;
         const presentation = Doc.MakeCopy(Doc.UserDoc().emptyPresentation as Doc, true);
-        const scenes = Cast(this.userDoc.myScenes, Doc) as Doc;
-        const sceneCount = DocListCast(scenes.data).length + 1;
+        const dashboards = Cast(this.userDoc.myDashboards, Doc) as Doc;
+        const dashboardCount = DocListCast(dashboards.data).length + 1;
         const freeformOptions: DocumentOptions = {
             x: 0,
             y: 400,
@@ -265,28 +265,28 @@ export class MainView extends React.Component {
             title: "Untitled Collection",
         };
         const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions);
-        const sceneDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [myCatalog] }], { title: `Scene ${sceneCount}` }, id, "row");
+        const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [myCatalog] }], { title: `Dashboard ${dashboardCount}` }, id, "row");
         Doc.AddDocToList(myCatalog, "data", freeformDoc);
         Doc.AddDocToList(myCatalog, "data", presentation);
         Doc.UserDoc().activePresentation = presentation;
         const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`);
         const toggleComic = ScriptField.MakeScript(`toggleComicMode()`);
-        const copyScene = ScriptField.MakeScript(`copyScene()`);
-        sceneDoc.contextMenuScripts = new List<ScriptField>([toggleTheme!, toggleComic!, copyScene!]);
-        sceneDoc.contextMenuLabels = new List<string>(["Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Scene"]);
+        const copyDashboard = ScriptField.MakeScript(`copyDashboard()`);
+        dashboardDoc.contextMenuScripts = new List<ScriptField>([toggleTheme!, toggleComic!, copyDashboard!]);
+        dashboardDoc.contextMenuLabels = new List<string>(["Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Dashboard"]);
 
-        Doc.AddDocToList(scenes, "data", sceneDoc);
+        Doc.AddDocToList(dashboards, "data", dashboardDoc);
         // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
-        setTimeout(() => this.openScene(sceneDoc), 0);
+        setTimeout(() => this.openDashboard(dashboardDoc), 0);
     }
 
     @action
-    openScene = (doc: Doc, fromHistory = false) => {
+    openDashboard = (doc: Doc, fromHistory = false) => {
         CurrentUserUtils.MainDocId = doc[Id];
 
-        if (doc) {  // this has the side-effect of setting the main container since we're assigning the active/guest scene
+        if (doc) {  // this has the side-effect of setting the main container since we're assigning the active/guest dashboard
             !("presentationView" in doc) && (doc.presentationView = new List<Doc>([Docs.Create.TreeDocument([], { title: "Presentation" })]));
-            this.userDoc ? (this.userDoc.activeScene = doc) : (CurrentUserUtils.GuestScene = doc);
+            this.userDoc ? (this.userDoc.activeDashboard = doc) : (CurrentUserUtils.GuestDashboard = doc);
         }
         const state = this._urlState;
         if (state.sharing === true && !this.userDoc) {
@@ -438,7 +438,7 @@ export class MainView extends React.Component {
     flyoutWidthFunc = () => this.flyoutWidth;
     addDocTabFunc = (doc: Doc, where: string, libraryPath?: Doc[]): boolean => {
         return where === "close" ? CollectionDockingView.CloseRightSplit(doc) :
-            doc.dockingConfig ? this.openScene(doc) :
+            doc.dockingConfig ? this.openDashboard(doc) :
                 CollectionDockingView.AddRightSplit(doc, libraryPath);
     }
     sidebarScreenToLocal = () => new Transform(0, (CollectionMenu.Instance.Pinned ? -35 : 0) - Number(SEARCH_PANEL_HEIGHT.replace("px", "")), 1);
@@ -977,12 +977,12 @@ export class MainView extends React.Component {
 }
 Scripting.addGlobal(function selectMainMenu(doc: Doc, title: string) { MainView.Instance.selectMenu(doc); });
 Scripting.addGlobal(function toggleComicMode() { Doc.UserDoc().fontFamily = "Comic Sans MS"; Doc.UserDoc().renderStyle = Doc.UserDoc().renderStyle === "comic" ? undefined : "comic"; });
-Scripting.addGlobal(function copyScene() {
-    const copiedScene = Doc.MakeCopy(Cast(Doc.UserDoc().activeScene, Doc, null), true);
-    const scenes = Cast(Doc.UserDoc().myScenes, Doc, null);
-    Doc.AddDocToList(scenes, "data", copiedScene);
+Scripting.addGlobal(function copyDashboard() {
+    const copiedDashboard = Doc.MakeCopy(Cast(Doc.UserDoc().activeDashboard, Doc, null), true);
+    const dashboards = Cast(Doc.UserDoc().myDashboards, Doc, null);
+    Doc.AddDocToList(dashboards, "data", copiedDashboard);
     // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
-    setTimeout(() => MainView.Instance.openScene(copiedScene), 0);
+    setTimeout(() => MainView.Instance.openDashboard(copiedDashboard), 0);
 });
 Scripting.addGlobal(function importDocument() { return MainView.Instance.importDocument(); },
     "imports files from device directly into the import sidebar");
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 6338e69a4..2f84065ec 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -31,9 +31,10 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV
 import { listSpec } from '../../../fields/Schema';
 import { clamp } from 'lodash';
 import { PresBox } from '../nodes/PresBox';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { InteractionUtils } from '../../util/InteractionUtils';
 import { InkTool } from '../../../fields/InkField';
+import { List } from '../../../fields/List';
+import { lstat } from 'fs';
 const _global = (window /* browser */ || global /* node */) as any;
 
 @observer
@@ -79,9 +80,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
         } else {
             config = {
                 type: 'row',
-                content: dragDocs.map((doc, i) => {
-                    CollectionDockingView.makeDocumentConfig(doc);
-                })
+                content: dragDocs.map((doc, i) => CollectionDockingView.makeDocumentConfig(doc))
             };
         }
         const div = document.createElement("div");
@@ -96,7 +95,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
     @action
     public OpenFullScreen(docView: DocumentView, libraryPath?: Doc[]) {
         if (docView.props.Document._viewType === CollectionViewType.Docking && docView.props.Document.layoutKey === "layout") {
-            return MainView.Instance.openScene(docView.props.Document);
+            return MainView.Instance.openDashboard(docView.props.Document);
         }
         const document = Doc.MakeAlias(docView.props.Document);
         const newItemStackConfig = {
@@ -154,7 +153,6 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
         this._goldenLayout.root.callDownwards('setSize', [this._goldenLayout.width, this._goldenLayout.height]);
         this._goldenLayout.emit('stateChanged');
         this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig());
-        if (removed) CollectionDockingView.Instance._removedDocs.push(removed);
         this.stateChanged();
     }
     @undoBatch
@@ -410,8 +408,8 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                         // Because this is in a set timeout, if this component unmounts right after mounting,
                         // we will leak a GoldenLayout, because we try to destroy it before we ever create it
                         setTimeout(() => this.setupGoldenLayout(), 1);
-                        DocListCast((Doc.UserDoc().myScenes as Doc).data).map(d => d.sceneBrush = false);
-                        this.props.Document.sceneBrush = true;
+                        DocListCast((Doc.UserDoc().myDashboards as Doc).data).map(d => d.dashboardBrush = false);
+                        this.props.Document.dashboardBrush = true;
                     }
                     this._ignoreStateChange = "";
                 }, { fireImmediately: true });
@@ -421,7 +419,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
     }
     componentWillUnmount: () => void = () => {
         try {
-            this.props.Document.sceneBrush = false;
+            this.props.Document.dashboardBrush = false;
             this._goldenLayout.unbind('itemDropped', this.itemDropped);
             this._goldenLayout.unbind('tabCreated', this.tabCreated);
             this._goldenLayout.unbind('stackCreated', this.stackCreated);
@@ -481,8 +479,16 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
 
         if (docids) {
             const docs = (await Promise.all(docids.map(id => DocServer.GetRefField(id)))).filter(f => f).map(f => f as Doc);
-            docs.map(doc => Doc.AddDocToList(Doc.GetProto(this.props.Document), this.props.fieldKey, doc));
-            // Doc.GetProto(this.props.Document)[this.props.fieldKey] = new List<Doc>(docs);
+            const sublists = DocListCast(this.props.Document[this.props.fieldKey]);
+            const tabs = Cast(sublists[0], Doc, null);
+            const other = Cast(sublists[1], Doc, null);
+            const tabdocs = DocListCast(tabs.data);
+            const otherdocs = DocListCast(other.data);
+            Doc.GetProto(tabs).data = new List<Doc>(docs);
+            const otherSet = new Set<Doc>();
+            otherdocs.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc));
+            tabdocs.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc));
+            Doc.GetProto(other).data = new List<Doc>(Array.from(otherSet.values()));
         }
     }
 
@@ -586,7 +592,6 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                 const doc = await DocServer.GetRefField(tab.contentItem.config.props.documentId);
                 if (doc instanceof Doc) {
                     const theDoc = doc;
-                    CollectionDockingView.Instance._removedDocs.push(theDoc);
 
                     const recent = await Cast(Doc.UserDoc().myRecentlyClosed, Doc);
                     if (recent) {
@@ -607,7 +612,6 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
             }
         }
     }
-    _removedDocs: Doc[] = [];
 
     stackCreated = (stack: any) => {
         //stack.header.controlsContainer.find('.lm_popout').hide();
@@ -652,7 +656,6 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                             Doc.AddDocToList(recent, "data", doc, undefined, true, true);
                         }
                         const theDoc = doc;
-                        CollectionDockingView.Instance._removedDocs.push(theDoc);
                     }
                 });
                 //}
@@ -668,7 +671,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
 
     render() {
         if (this.props.renderDepth > 0) {
-            return <div style={{ width: "100%", height: "100%" }}>Nested scenes can't be rendered</div>;
+            return <div style={{ width: "100%", height: "100%" }}>Nested dashboards can't be rendered</div>;
         }
         return <div className="collectiondockingview-container" id="menuContainer"
             onPointerDown={this.onPointerDown} onPointerUp={this.onPointerUp} ref={this._containerRef} />;
@@ -834,7 +837,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
     addDocTab = (doc: Doc, location: string, libraryPath?: Doc[]) => {
         SelectionManager.DeselectAll();
         if (doc._viewType === CollectionViewType.Docking && doc.layoutKey === "layout") {
-            return MainView.Instance.openScene(doc);
+            return MainView.Instance.openDashboard(doc);
         } else if (location === "onRight") {
             return CollectionDockingView.AddRightSplit(doc, libraryPath);
         } else if (location === "close") {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 6eead6e6d..b78678bc3 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -471,7 +471,7 @@ class TreeView extends React.Component<TreeViewProps> {
                 style={{
                     fontWeight: this.doc.searchMatch !== undefined ? "bold" : undefined,
                     textDecoration: Doc.GetT(this.doc, "title", "string", true) ? "underline" : undefined,
-                    outline: BoolCast(this.doc.sceneBrush) ? "dashed 1px #06123232" : undefined,
+                    outline: BoolCast(this.doc.dashboardBrush) ? "dashed 1px #06123232" : undefined,
                     pointerEvents: this.props.active() || SnappingManager.GetIsDragging() ? undefined : "none"
                 }} >
                 {view}
@@ -725,9 +725,9 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
     }
     onContextMenu = (e: React.MouseEvent): void => {
         // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout
-        if (!e.isPropagationStopped() && this.doc === Doc.UserDoc().myScenes) {
-            ContextMenu.Instance.addItem({ description: "Create Scene", event: () => MainView.Instance.createNewScene(), icon: "plus" });
-            ContextMenu.Instance.addItem({ description: "Delete Scene", event: () => this.remove(this.doc), icon: "minus" });
+        if (!e.isPropagationStopped() && this.doc === Doc.UserDoc().myDashboards) {
+            ContextMenu.Instance.addItem({ description: "Create Dashboard", event: () => MainView.Instance.createNewDashboard(), icon: "plus" });
+            ContextMenu.Instance.addItem({ description: "Delete Dashboard", event: () => this.remove(this.doc), icon: "minus" });
             e.stopPropagation();
             e.preventDefault();
             ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index c75179252..12d2152b1 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -588,7 +588,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
             ChildLayoutString: this.childLayoutString,
         };
         const boxShadow = Doc.UserDoc().renderStyle === "comic" || this.props.Document.isBackground || this.collectionViewType === CollectionViewType.Linear ? undefined :
-            `${Cast(Doc.UserDoc().activeScene, Doc, null)?.darkScheme ? "rgb(30, 32, 31) " : "#9c9396 "} ${StrCast(this.props.Document.boxShadow, "0.2vw 0.2vw 0.8vw")}`;
+            `${Cast(Doc.UserDoc().activeDashboard, Doc, null)?.darkScheme ? "rgb(30, 32, 31) " : "#9c9396 "} ${StrCast(this.props.Document.boxShadow, "0.2vw 0.2vw 0.8vw")}`;
         return (<div className={"collectionView"} onContextMenu={this.onContextMenu}
             style={{ pointerEvents: this.props.Document.isBackground ? "none" : undefined, boxShadow }}>
             {this.showIsTagged()}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
index 6a320dfde..646ae94fb 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
@@ -359,7 +359,7 @@ export function computeTimelineLayout(
         groupNames.push({ type: "text", text: toLabel(Math.ceil(maxTime)), x: Math.ceil(maxTime - minTime) * scaling, y: 0, height: fontHeight, fontSize, payload: undefined });
     }
 
-    const divider = { type: "div", color: Cast(Doc.UserDoc().activeScene, Doc, null)?.darkScheme ? "dimGray" : "black", x: 0, y: 0, width: panelDim[0], height: -1, payload: undefined };
+    const divider = { type: "div", color: Cast(Doc.UserDoc().activeDashboard, Doc, null)?.darkScheme ? "dimGray" : "black", x: 0, y: 0, width: panelDim[0], height: -1, payload: undefined };
     return normalizeResults(panelDim, fontHeight, docMap, poolData, viewDefsToJSX, groupNames, (maxTime - minTime) * scaling, [divider]);
 
     function layoutDocsAtTime(keyDocs: Doc[], key: number) {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 8d9d1f729..91f12f004 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -564,8 +564,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
     @undoBatch @action
     deleteClicked = (): void => {
-        if (Doc.UserDoc().activeScene === this.props.Document) {
-            alert("Can't delete the active scene");
+        if (Doc.UserDoc().activeDashboard === this.props.Document) {
+            alert("Can't delete the active dashboard");
         } else {
             const selected = SelectionManager.SelectedDocuments().slice();
             SelectionManager.DeselectAll();
@@ -601,7 +601,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
     @undoBatch @action
     drop = async (e: Event, de: DragManager.DropEvent) => {
-        if (this.props.Document === Doc.UserDoc().activeScene) {
+        if (this.props.Document === Doc.UserDoc().activeDashboard) {
             alert("linking to document tabs not yet supported.  Drop link on document content.");
             return;
         }
@@ -1011,7 +1011,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         const fullDegree = Doc.isBrushedHighlightedDegree(this.props.Document);
         const borderRounding = this.layoutDoc.borderRounding;
         const localScale = fullDegree;
-        const highlightColors = Cast(Doc.UserDoc().activeScene, Doc, null)?.darkScheme ?
+        const highlightColors = Cast(Doc.UserDoc().activeDashboard, Doc, null)?.darkScheme ?
             ["transparent", "#65350c", "#65350c", "yellow", "magenta", "cyan", "orange"] :
             ["transparent", "maroon", "maroon", "yellow", "magenta", "cyan", "orange"];
         const highlightStyles = ["solid", "dashed", "solid", "solid", "solid", "solid", "solid"];
diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx
index 0e965ba9a..31dd92b59 100644
--- a/src/client/views/nodes/formattedText/DashDocView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocView.tsx
@@ -175,7 +175,7 @@ export class DashDocView extends React.Component<IDashDocView> {
         const outerStyle = {
             position: "relative" as "relative",
             textIndent: "0",
-            border: "1px solid " + StrCast(this._textBox.Document.color, (Cast(Doc.UserDoc().activeScene, Doc, null).darkScheme ? "dimGray" : "lightGray")),
+            border: "1px solid " + StrCast(this._textBox.Document.color, (Cast(Doc.UserDoc().activeDashboard, Doc, null).darkScheme ? "dimGray" : "lightGray")),
             width: this.props.node.props.width,
             height: this.props.node.props.height,
             display: this.props.node.props.hidden ? "none" : "inline-block",
@@ -202,7 +202,7 @@ export class DashDocView extends React.Component<IDashDocView> {
                 ({ dim, color }) => {
                     spanStyle.width = outerStyle.width = Math.max(20, dim[0]) + "px";
                     spanStyle.height = outerStyle.height = Math.max(20, dim[1]) + "px";
-                    outerStyle.border = "1px solid " + StrCast(finalLayout.color, (Cast(Doc.UserDoc().activeScene, Doc, null).darkScheme ? "dimGray" : "lightGray"));
+                    outerStyle.border = "1px solid " + StrCast(finalLayout.color, (Cast(Doc.UserDoc().activeDashboard, Doc, null).darkScheme ? "dimGray" : "lightGray"));
                 }, { fireImmediately: true });
 
             if (node.attrs.width !== dashDoc._width + "px" || node.attrs.height !== dashDoc._height + "px") {
diff --git a/src/client/views/nodes/formattedText/RichTextSchema.tsx b/src/client/views/nodes/formattedText/RichTextSchema.tsx
index 78c76efcb..a85dacc7e 100644
--- a/src/client/views/nodes/formattedText/RichTextSchema.tsx
+++ b/src/client/views/nodes/formattedText/RichTextSchema.tsx
@@ -43,7 +43,7 @@ export class DashDocView {
         this._outer = document.createElement("span");
         this._outer.style.position = "relative";
         this._outer.style.textIndent = "0";
-        this._outer.style.border = "1px solid " + StrCast(tbox.layoutDoc.color, (Cast(Doc.UserDoc().activeScene, Doc, null).darkScheme ? "dimGray" : "lightGray"));
+        this._outer.style.border = "1px solid " + StrCast(tbox.layoutDoc.color, (Cast(Doc.UserDoc().activeDashboard, Doc, null).darkScheme ? "dimGray" : "lightGray"));
         this._outer.style.width = node.attrs.width;
         this._outer.style.height = node.attrs.height;
         this._outer.style.display = node.attrs.hidden ? "none" : "inline-block";
@@ -126,7 +126,7 @@ export class DashDocView {
             this._reactionDisposer = reaction(() => ({ dim: [finalLayout[WidthSym](), finalLayout[HeightSym]()], color: finalLayout.color }), ({ dim, color }) => {
                 this._dashSpan.style.width = this._outer.style.width = Math.max(20, dim[0]) + "px";
                 this._dashSpan.style.height = this._outer.style.height = Math.max(20, dim[1]) + "px";
-                this._outer.style.border = "1px solid " + StrCast(finalLayout.color, (Cast(Doc.UserDoc().activeScene, Doc, null).darkScheme ? "dimGray" : "lightGray"));
+                this._outer.style.border = "1px solid " + StrCast(finalLayout.color, (Cast(Doc.UserDoc().activeDashboard, Doc, null).darkScheme ? "dimGray" : "lightGray"));
             }, { fireImmediately: true });
 
             const doReactRender = (finalLayout: Doc, resolvedDataDoc: Doc) => {
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index fc8c45c25..41b997285 100644
--- a/src/mobile/MobileInterface.tsx
+++ b/src/mobile/MobileInterface.tsx
@@ -58,7 +58,7 @@ export class MobileInterface extends React.Component {
     @observable private _menuListView: boolean = false; //to switch between menu view (list / icon)
     @observable private _ink: boolean = false; //toggle whether ink is being dispalyed
     @observable private _homeMenu: boolean = true; // to determine whether currently at home menu
-    @observable private scenes: Doc | null = null; // currently selected document
+    @observable private dashboards: Doc | null = null; // currently selected document
     @observable private _activeDoc: Doc = this._mainDoc; // doc updated as the active mobile page is updated (initially home menu)
     @observable private _homeDoc: Doc = this._mainDoc; // home menu as a document
     @observable private _parents: Array<Doc> = []; // array of parent docs (for pathbar)
@@ -136,19 +136,19 @@ export class MobileInterface extends React.Component {
     back = () => {
         const header = document.getElementById("header") as HTMLElement;
         const doc = Cast(this._parents.pop(), Doc) as Doc; // Parent document
-        // Case 1: Parent document is 'scenes'
+        // Case 1: Parent document is 'dashboards'
         if (doc === Cast(this._library, Doc) as Doc) {
-            this.scenes = null;
+            this.dashboards = null;
             this._library.then(library => this.switchCurrentView(library));
             // Case 2: Parent document is the 'home' menu (root node)
         } else if (doc === Cast(this._homeDoc, Doc) as Doc) {
             this._homeMenu = true;
             this._parents = [];
-            this.scenes = null;
+            this.dashboards = null;
             this.switchCurrentView(this._homeDoc);
             // Case 3: Parent document is any document
         } else if (doc) {
-            this.scenes = doc;
+            this.dashboards = doc;
             this.switchCurrentView(doc);
             this._homeMenu = false;
             header.textContent = String(doc.title);
@@ -164,7 +164,7 @@ export class MobileInterface extends React.Component {
         if (!this._homeMenu || this._sidebarActive) {
             this._homeMenu = true;
             this._parents = [];
-            this.scenes = null;
+            this.dashboards = null;
             this.switchCurrentView(this._homeDoc);
         }
         if (this._sidebarActive) {
@@ -173,14 +173,14 @@ export class MobileInterface extends React.Component {
     }
 
     /**
-     * Return to primary Scene in library (Scenes Doc)
+     * Return to primary Dashboard in library (Dashboards Doc)
      */
     @action
     returnMain = () => {
         this._parents = [this._homeDoc];
         this._library.then(library => this.switchCurrentView(library));
         this._homeMenu = false;
-        this.scenes = null;
+        this.dashboards = null;
     }
 
     /**
@@ -194,7 +194,7 @@ export class MobileInterface extends React.Component {
     /**
      * DocumentView for graphic display of all documents
      */
-    @computed get displayScenes() {
+    @computed get displayDashboards() {
         return !this.mainContainer ? (null) :
             <div style={{ position: "relative", top: '198px', height: `calc(100% - 350px)`, width: "100%", left: "0%" }}>
                 <DocumentView
@@ -243,7 +243,7 @@ export class MobileInterface extends React.Component {
                 this._parents.push(this._activeDoc);
                 this.switchCurrentView(doc);
                 this._homeMenu = false;
-                this.scenes = doc;
+                this.dashboards = doc;
             }
         });
     }
@@ -258,7 +258,7 @@ export class MobileInterface extends React.Component {
         this._parents.push(this._activeDoc);
         this.switchCurrentView(doc);
         this._homeMenu = false;
-        this.scenes = doc;
+        this.dashboards = doc;
         this.toggleSidebar();
     }
 
@@ -290,13 +290,13 @@ export class MobileInterface extends React.Component {
     handlePathClick = async (doc: Doc, index: number) => {
         const library = await this._library;
         if (doc === library) {
-            this.scenes = null;
+            this.dashboards = null;
             this.switchCurrentView(doc);
             this._parents.length = index;
         } else if (doc === this._homeDoc) {
             this.returnHome();
         } else {
-            this.scenes = doc;
+            this.dashboards = doc;
             this.switchCurrentView(doc);
             this._parents.length = index;
         }
@@ -321,13 +321,13 @@ export class MobileInterface extends React.Component {
                 </div>
             );
         }
-        // stores scenes documents as 'scenes' variable
-        let scenes = Cast(Doc.UserDoc().myScenes, Doc) as Doc;
-        if (this.scenes) {
-            scenes = this.scenes;
+        // stores dashboards documents as 'dashboards' variable
+        let dashboards = Cast(Doc.UserDoc().myDashboards, Doc) as Doc;
+        if (this.dashboards) {
+            dashboards = this.dashboards;
         }
         // returns a list of navbar buttons as 'buttons'
-        const buttons = DocListCast(scenes.data).map((doc: Doc, index: any) => {
+        const buttons = DocListCast(dashboards.data).map((doc: Doc, index: any) => {
             if (doc.type !== "ink") {
                 return (
                     <div
@@ -357,7 +357,7 @@ export class MobileInterface extends React.Component {
                 {this.renderPathbar()}
                 <div className={`sidebar ${this._sidebarActive ? "active" : ""}`}>
                     <div className="sidebarButtons">
-                        {this.scenes ?
+                        {this.dashboards ?
                             <>
                                 {buttons}
                                 <div
@@ -365,7 +365,7 @@ export class MobileInterface extends React.Component {
                                     onClick={this.returnMain}
                                     style={{ opacity: 0.7 }}>
                                     <FontAwesomeIcon className="right" icon="angle-double-left" size="lg" />
-                                    <div className="item-type">Return to scenes</div>
+                                    <div className="item-type">Return to dashboards</div>
                                 </div>
                             </> :
                             <>
@@ -373,9 +373,9 @@ export class MobileInterface extends React.Component {
                                 <div
                                     className="item"
                                     style={{ opacity: 0.7 }}
-                                    onClick={() => this.createNewScene()}>
+                                    onClick={() => this.createNewDashboard()}>
                                     <FontAwesomeIcon className="right" icon="plus" size="lg" />
-                                    <div className="item-type">Create New Scene</div>
+                                    <div className="item-type">Create New Dashboard</div>
                                 </div>
                             </>
                         }
@@ -388,27 +388,27 @@ export class MobileInterface extends React.Component {
     }
 
     /**
-     * Handles the 'Create New Scene' button in the menu (taken from MainView.tsx)
+     * Handles the 'Create New Dashboard' button in the menu (taken from MainView.tsx)
      */
     @action
-    createNewScene = async (id?: string) => {
-        const scens = Cast(Doc.UserDoc().myScenes, Doc) as Doc;
-        const sceneCount = DocListCast(scens.data).length + 1;
+    createNewDashboard = async (id?: string) => {
+        const scens = Cast(Doc.UserDoc().myDashboards, Doc) as Doc;
+        const dashboardCount = DocListCast(scens.data).length + 1;
         const freeformOptions: DocumentOptions = {
             x: 0,
             y: 400,
-            title: "Collection " + sceneCount,
+            title: "Collection " + dashboardCount,
         };
         const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions);
-        const sceneDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [Doc.UserDoc().myCatalog as Doc] }], { title: `Scene ${sceneCount}` }, id, "row");
+        const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [Doc.UserDoc().myCatalog as Doc] }], { title: `Dashboard ${dashboardCount}` }, id, "row");
 
         const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`);
         const toggleComic = ScriptField.MakeScript(`toggleComicMode()`);
-        const cloneScene = ScriptField.MakeScript(`cloneScene()`);
-        sceneDoc.contextMenuScripts = new List<ScriptField>([toggleTheme!, toggleComic!, cloneScene!]);
-        sceneDoc.contextMenuLabels = new List<string>(["Toggle Theme Colors", "Toggle Comic Mode", "New Scene Layout"]);
+        const cloneDashboard = ScriptField.MakeScript(`cloneDashboard()`);
+        dashboardDoc.contextMenuScripts = new List<ScriptField>([toggleTheme!, toggleComic!, cloneDashboard!]);
+        dashboardDoc.contextMenuLabels = new List<string>(["Toggle Theme Colors", "Toggle Comic Mode", "New Dashboard Layout"]);
 
-        Doc.AddDocToList(scens, "data", sceneDoc);
+        Doc.AddDocToList(scens, "data", dashboardDoc);
     }
 
     // Button for switching between pen and ink mode
@@ -612,7 +612,7 @@ export class MobileInterface extends React.Component {
     }
 
     // Radial menu can only be used if it is a colleciton and it is not a homeDoc 
-    // (and cannot be used on Scene to avoid pin to presentation opening on right)
+    // (and cannot be used on Dashboard to avoid pin to presentation opening on right)
     @computed get displayRadialMenu() {
         return this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc &&
             this._activeDoc._viewType !== CollectionViewType.Docking ? <RadialMenu /> : (null);
@@ -657,7 +657,7 @@ export class MobileInterface extends React.Component {
                         {this.drawInk}
                         {this.uploadImageButton}
                     </div>
-                    {this.displayScenes}
+                    {this.displayDashboards}
                     {this.renderDefaultContent}
                 </GestureOverlay>
                 {this.displayRadialMenu}
@@ -669,7 +669,7 @@ export class MobileInterface extends React.Component {
 
 //Global functions for mobile menu
 Scripting.addGlobal(function switchToMobileLibrary() { return MobileInterface.Instance.switchToLibrary(); },
-    "opens the library to navigate through scenes on Dash Mobile");
+    "opens the library to navigate through dashboards on Dash Mobile");
 Scripting.addGlobal(function openMobileUploads() { return MobileInterface.Instance.toggleUpload(); },
     "opens the upload files menu for Dash Mobile");
 Scripting.addGlobal(function switchToMobileUploadCollection() { return MobileInterface.Instance.switchToMobileUploads(); },
-- 
cgit v1.2.3-70-g09d2


From 88b06945c8a1fcb7bc518de878a4894de70dda94 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sat, 22 Aug 2020 14:21:41 -0400
Subject: major overhaul of search to avoid writing anything to filtered
 documents and to make the UI work properly.

---
 src/Utils.ts                                       |   2 +
 src/client/documents/Documents.ts                  |   5 +-
 src/client/util/CurrentUserUtils.ts                |   2 +-
 src/client/views/GestureOverlay.tsx                |   3 +-
 src/client/views/MainView.tsx                      |  11 +-
 src/client/views/OverlayView.tsx                   |   3 +-
 src/client/views/Palette.tsx                       |   3 +-
 src/client/views/TemplateMenu.tsx                  |   3 +-
 .../views/collections/CollectionDockingView.tsx    |   4 +-
 .../views/collections/CollectionLinearView.tsx     |   1 +
 src/client/views/collections/CollectionMenu.tsx    |  14 ++-
 .../views/collections/CollectionSchemaCells.tsx    |   6 +-
 .../views/collections/CollectionSchemaHeaders.tsx  |  26 ++---
 .../views/collections/CollectionSchemaView.scss    |   3 +
 .../views/collections/CollectionSchemaView.tsx     |  17 +--
 .../views/collections/CollectionStackingView.tsx   |   1 +
 src/client/views/collections/CollectionSubView.tsx |  26 ++---
 .../views/collections/CollectionTreeView.tsx       |   4 +-
 src/client/views/collections/CollectionView.tsx    |   3 +-
 src/client/views/collections/SchemaTable.tsx       |   3 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   1 +
 .../collectionFreeForm/PropertiesView.tsx          |   3 +-
 .../CollectionMulticolumnView.tsx                  |   1 +
 .../CollectionMultirowView.tsx                     |   1 +
 src/client/views/nodes/DocHolderBox.tsx            |   2 +
 src/client/views/nodes/DocumentView.tsx            |   2 +
 src/client/views/nodes/FieldView.tsx               |   1 +
 src/client/views/nodes/ImageBox.tsx                |   1 +
 src/client/views/nodes/LinkDocPreview.tsx          |   3 +-
 src/client/views/nodes/PDFBox.tsx                  |   2 +-
 src/client/views/nodes/VideoBox.tsx                |   1 +
 src/client/views/nodes/WebBox.tsx                  |   1 +
 .../views/nodes/formattedText/DashDocView.tsx      |   3 +-
 .../formattedText/FormattedTextBoxComment.tsx      |   3 +-
 .../views/nodes/formattedText/RichTextSchema.tsx   |   1 +
 src/client/views/pdf/PDFViewer.tsx                 |   1 +
 .../views/presentationview/PresElementBox.tsx      |   1 +
 src/client/views/search/SearchBox.tsx              | 128 ++++++++-------------
 src/fields/Doc.ts                                  |  15 +--
 src/fields/List.ts                                 |  25 ++--
 src/mobile/AudioUpload.tsx                         |   3 +-
 src/mobile/MobileInterface.tsx                     |   3 +-
 42 files changed, 173 insertions(+), 169 deletions(-)

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

diff --git a/src/Utils.ts b/src/Utils.ts
index d9a5353e8..3ff05104f 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -422,6 +422,8 @@ export function returnEmptyString() { return ""; }
 
 export function returnEmptyFilter() { return [] as string[]; }
 
+export function returnEmptyDoclist() { return [] as Doc[]; }
+
 export let emptyPath = [];
 
 export function emptyFunction() { }
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 4544e0e3e..49da4f9eb 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -72,6 +72,7 @@ export interface DocumentOptions {
     _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
@@ -822,8 +823,8 @@ 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), { treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id);
-            const tabs = TreeDocument(documents, { title: "Active Tabs", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data" });
-            const all = TreeDocument([], { title: "Inactive Tabs", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data" });
+            const tabs = TreeDocument(documents, { title: "On-Screen Tabs", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data" });
+            const all = TreeDocument([], { title: "Off-Screen Tabs", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data" });
             Doc.GetProto(inst).data = new List<Doc>([tabs, all]);
             return inst;
         }
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index b907a8e4c..c09a227cf 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -525,7 +525,7 @@ export class CurrentUserUtils {
     static setupSearchPanel(doc: Doc) {
         if (doc["search-panel"] === undefined) {
             doc["search-panel"] = new PrefetchProxy(Docs.Create.SearchDocument({
-                _width: 500, _height: 400, backgroundColor: "dimGray", ignoreClick: true,
+                _width: 500, _height: 400, backgroundColor: "dimGray", ignoreClick: true, _searchDoc: true,
                 childDropAction: "alias", lockedPosition: true, _viewType: CollectionViewType.Schema, _chromeStatus: "disabled", title: "sidebar search stack", system: true
             })) as any as Doc;
         }
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 2d41343b3..260cffc90 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -7,7 +7,7 @@ import { Cast, FieldValue, NumCast } from "../../fields/Types";
 import MobileInkOverlay from "../../mobile/MobileInkOverlay";
 import { GestureUtils } from "../../pen-gestures/GestureUtils";
 import { MobileInkOverlayContent } from "../../server/Message";
-import { emptyFunction, emptyPath, returnEmptyString, returnFalse, returnOne, returnTrue, returnZero, returnEmptyFilter, setupMoveUpEvents } from "../../Utils";
+import { emptyFunction, emptyPath, returnEmptyString, returnFalse, returnOne, returnTrue, returnZero, returnEmptyFilter, setupMoveUpEvents, returnEmptyDoclist } from "../../Utils";
 import { CognitiveServices } from "../cognitive_services/CognitiveServices";
 import { DocUtils } from "../documents/Documents";
 import { CurrentUserUtils } from "../util/CurrentUserUtils";
@@ -935,6 +935,7 @@ export default class GestureOverlay extends Touchable {
                 whenActiveChanged={emptyFunction}
                 bringToFront={emptyFunction}
                 docFilters={returnEmptyFilter}
+                searchFilterDocs={returnEmptyDoclist}
                 ContainingCollectionView={undefined}
                 ContainingCollectionDoc={undefined}
             />;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index bc5483644..979f803bf 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -16,7 +16,7 @@ import { listSpec } from '../../fields/Schema';
 import { ScriptField } from '../../fields/ScriptField';
 import { BoolCast, Cast, FieldValue, StrCast } from '../../fields/Types';
 import { TraceMobx } from '../../fields/util';
-import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick, Utils } from '../../Utils';
+import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick, Utils, returnEmptyDoclist } from '../../Utils';
 import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager';
 import { DocServer } from '../DocServer';
 import { Docs, DocumentOptions } from '../documents/Documents';
@@ -206,7 +206,7 @@ export class MainView extends React.Component {
                 }
             });
             if (check === false) {
-                SearchBox.Instance.closeSearch();
+                SearchBox.Instance.resetSearch(true);
             }
         }
 
@@ -394,6 +394,7 @@ export class MainView extends React.Component {
             whenActiveChanged={emptyFunction}
             bringToFront={emptyFunction}
             docFilters={returnEmptyFilter}
+            searchFilterDocs={returnEmptyDoclist}
             ContainingCollectionView={undefined}
             ContainingCollectionDoc={undefined}
             renderDepth={-1}
@@ -476,6 +477,7 @@ export class MainView extends React.Component {
                     whenActiveChanged={emptyFunction}
                     bringToFront={emptyFunction}
                     docFilters={returnEmptyFilter}
+                    searchFilterDocs={returnEmptyDoclist}
                     ContainingCollectionView={undefined}
                     ContainingCollectionDoc={undefined}
                     relative={true}
@@ -510,6 +512,7 @@ export class MainView extends React.Component {
                 whenActiveChanged={emptyFunction}
                 bringToFront={emptyFunction}
                 docFilters={returnEmptyFilter}
+                searchFilterDocs={returnEmptyDoclist}
                 ContainingCollectionView={undefined}
                 ContainingCollectionDoc={undefined}
                 relative={true}
@@ -703,6 +706,7 @@ export class MainView extends React.Component {
                     focus={emptyFunction}
                     whenActiveChanged={emptyFunction}
                     docFilters={returnEmptyFilter}
+                    searchFilterDocs={returnEmptyDoclist}
                     ContainingCollectionView={undefined}
                     ContainingCollectionDoc={undefined} />
             </div>;
@@ -775,6 +779,7 @@ export class MainView extends React.Component {
                 whenActiveChanged={emptyFunction}
                 bringToFront={emptyFunction}
                 docFilters={returnEmptyFilter}
+                searchFilterDocs={returnEmptyDoclist}
                 ContainingCollectionView={undefined}
                 ContainingCollectionDoc={undefined}
             /></div>
@@ -808,6 +813,7 @@ export class MainView extends React.Component {
                     NativeWidth={() => 800}
                     ContentScaling={returnOne}
                     docFilters={returnEmptyFilter}
+                    searchFilterDocs={returnEmptyDoclist}
                 />
             </div>;
     }
@@ -878,6 +884,7 @@ export class MainView extends React.Component {
                             NativeWidth={() => 800}
                             ContentScaling={returnOne}
                             docFilters={returnEmptyFilter}
+                            searchFilterDocs={returnEmptyDoclist}
                         />
                     </div>;
                 </span>, ele);
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 49580cde4..001135340 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -4,7 +4,7 @@ import * as React from "react";
 import { Doc, DocListCast, Opt } from "../../fields/Doc";
 import { Id } from "../../fields/FieldSymbols";
 import { NumCast, Cast } from "../../fields/Types";
-import { emptyFunction, emptyPath, returnEmptyString, returnFalse, returnOne, returnTrue, returnZero, Utils, setupMoveUpEvents, returnEmptyFilter } from "../../Utils";
+import { emptyFunction, emptyPath, returnEmptyString, returnFalse, returnOne, returnTrue, returnZero, Utils, setupMoveUpEvents, returnEmptyFilter, returnEmptyDoclist } from "../../Utils";
 import { Transform } from "../util/Transform";
 import { CollectionFreeFormLinksView } from "./collections/collectionFreeForm/CollectionFreeFormLinksView";
 import { DocumentView } from "./nodes/DocumentView";
@@ -205,6 +205,7 @@ export class OverlayView extends React.Component {
                     addDocTab={returnFalse}
                     pinToPres={emptyFunction}
                     docFilters={returnEmptyFilter}
+                    searchFilterDocs={returnEmptyDoclist}
                     ContainingCollectionView={undefined}
                     ContainingCollectionDoc={undefined} />
             </div>;
diff --git a/src/client/views/Palette.tsx b/src/client/views/Palette.tsx
index 0a4334302..92c3f09b4 100644
--- a/src/client/views/Palette.tsx
+++ b/src/client/views/Palette.tsx
@@ -3,7 +3,7 @@ import { observer } from "mobx-react";
 import * as React from "react";
 import { Doc } from "../../fields/Doc";
 import { NumCast } from "../../fields/Types";
-import { emptyFunction, emptyPath, returnEmptyString, returnZero, returnFalse, returnOne, returnTrue, returnEmptyFilter } from "../../Utils";
+import { emptyFunction, emptyPath, returnEmptyString, returnZero, returnFalse, returnOne, returnTrue, returnEmptyFilter, returnEmptyDoclist } from "../../Utils";
 import { Transform } from "../util/Transform";
 import { DocumentView } from "./nodes/DocumentView";
 import "./Palette.scss";
@@ -60,6 +60,7 @@ export default class Palette extends React.Component<PaletteProps> {
                             whenActiveChanged={emptyFunction}
                             bringToFront={emptyFunction}
                             docFilters={returnEmptyFilter}
+                            searchFilterDocs={returnEmptyDoclist}
                             ContainingCollectionView={undefined}
                             ContainingCollectionDoc={undefined} />
                         <div className="palette-cover" style={{ transform: `translate(${Math.max(0, this._selectedIndex) * 50.75 + 23}px, 0px)` }}></div>
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index eb20fc257..e4ba45648 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -10,7 +10,7 @@ import { Doc, DocListCast } from "../../fields/Doc";
 import { Docs, DocUtils, } from "../documents/Documents";
 import { StrCast, Cast } from "../../fields/Types";
 import { CollectionTreeView } from "./collections/CollectionTreeView";
-import { returnTrue, emptyFunction, returnFalse, returnOne, emptyPath, returnZero, returnEmptyFilter } from "../../Utils";
+import { returnTrue, emptyFunction, returnFalse, returnOne, emptyPath, returnZero, returnEmptyFilter, returnEmptyDoclist } from "../../Utils";
 import { Transform } from "../util/Transform";
 import { ScriptField, ComputedField } from "../../fields/ScriptField";
 import { Scripting } from "../util/Scripting";
@@ -133,6 +133,7 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
                 ContainingCollectionDoc={undefined}
                 ContainingCollectionView={undefined}
                 docFilters={returnEmptyFilter}
+                searchFilterDocs={returnEmptyDoclist}
                 rootSelected={returnFalse}
                 onCheckedClick={this.scriptField}
                 onChildClick={this.scriptField}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 83321d6e0..74b1e5714 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -14,7 +14,7 @@ import { FieldId } from "../../../fields/RefField";
 import { listSpec } from '../../../fields/Schema';
 import { Cast, NumCast, StrCast } from "../../../fields/Types";
 import { TraceMobx } from '../../../fields/util';
-import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero, setupMoveUpEvents, Utils } from "../../../Utils";
+import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero, setupMoveUpEvents, Utils, returnEmptyDoclist } from "../../../Utils";
 import { DocServer } from "../../DocServer";
 import { Docs } from '../../documents/Documents';
 import { DocumentManager } from '../../util/DocumentManager';
@@ -938,6 +938,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                 addDocTab={this.addDocTab}
                 pinToPres={DockedFrameRenderer.PinDoc}
                 docFilters={returnEmptyFilter}
+                searchFilterDocs={returnEmptyDoclist}
                 fitToBox={true}
             />
             <div className="miniOverlay" onPointerDown={this.miniDown} >
@@ -979,6 +980,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
                 addDocTab={this.addDocTab}
                 pinToPres={DockedFrameRenderer.PinDoc}
                 docFilters={returnEmptyFilter}
+                searchFilterDocs={returnEmptyDoclist}
                 ContainingCollectionView={undefined}
                 ContainingCollectionDoc={undefined} />
             {document._viewType === CollectionViewType.Freeform && !this._document?.hideMinimap ? this.renderMiniMap() : (null)}
diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx
index e1b07077e..0fd18034f 100644
--- a/src/client/views/collections/CollectionLinearView.tsx
+++ b/src/client/views/collections/CollectionLinearView.tsx
@@ -166,6 +166,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
                                 whenActiveChanged={emptyFunction}
                                 bringToFront={emptyFunction}
                                 docFilters={this.props.docFilters}
+                                searchFilterDocs={this.props.searchFilterDocs}
                                 ContainingCollectionView={undefined}
                                 ContainingCollectionDoc={undefined} />
                         </div>;
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 388eda2b3..5580c32f2 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -131,7 +131,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
     _contentCommand = {
         params: ["target", "source"], title: "set content",
         script: "getProto(self.target).data = copyField(self.source);",
-        immediate: undoBatch((source: Doc[]) => Doc.GetProto(this.target).data = new List<Doc>(source)), // Doc.aliasDocs(source),
+        immediate: undoBatch((source: Doc[]) => Doc.GetProto(this.target).data = new List<Doc>(source)),
         initialize: emptyFunction,
     };
     _onClickCommand = {
@@ -180,12 +180,16 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
     };
     _saveFilterCommand = {
         params: ["target"], title: "save filter",
-        script: "self.target._docFilters = copyField(self['target-docFilters']);",
-        immediate: undoBatch((source: Doc[]) => this.target._docFilters = undefined),
-        initialize: (button: Doc) => { button['target-docFilters'] = this.target._docFilters instanceof ObjectField ? ObjectField.MakeCopy(this.target._docFilters as any as ObjectField) : ""; },
+        script: `self.target._docFilters = copyField(self['target-docFilters']); 
+                 self.target._searchFilterDocs = compareLists(self['target-searchFilterDocs'],self.target._searchFilterDocs) ? undefined: copyField(self['target-searchFilterDocs']);`,
+        immediate: undoBatch((source: Doc[]) => { this.target._docFilters = undefined; this.target._searchFilterDocs = undefined; }),
+        initialize: (button: Doc) => {
+            button['target-docFilters'] = this.target._docFilters instanceof ObjectField ? ObjectField.MakeCopy(this.target._docFilters as any as ObjectField) : undefined;
+            button['target-searchFilterDocs'] = this.target._searchFilterDocs instanceof ObjectField ? ObjectField.MakeCopy(this.target._searchFilterDocs as any as ObjectField) : undefined;
+        },
     };
 
-    @computed get _freeform_commands() { return Doc.UserDoc().noviceMode ? [this._viewCommand] : [this._viewCommand, this._saveFilterCommand, this._contentCommand, this._templateCommand, this._narrativeCommand]; }
+    @computed get _freeform_commands() { return Doc.UserDoc().noviceMode ? [this._viewCommand, this._saveFilterCommand] : [this._viewCommand, this._saveFilterCommand, this._contentCommand, this._templateCommand, this._narrativeCommand]; }
     @computed get _stacking_commands() { return Doc.UserDoc().noviceMode ? undefined : [this._contentCommand, this._templateCommand]; }
     @computed get _masonry_commands() { return Doc.UserDoc().noviceMode ? undefined : [this._contentCommand, this._templateCommand]; }
     @computed get _schema_commands() { return Doc.UserDoc().noviceMode ? undefined : [this._templateCommand, this._narrativeCommand]; }
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 4bd69041b..2f1f7a90f 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -229,7 +229,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         const fieldIsDoc = (type === "document" && typeof field === "object") || (typeof field === "object" && doc);
 
         const onItemDown = async (e: React.PointerEvent) => {
-            if (this.props.Document._searchDoc !== undefined) {
+            if (this.props.Document._searchDoc) {
                 const doc = Doc.GetProto(this.props.rowProps.original);
                 const aliasdoc = await SearchUtil.GetAliasesOfDocument(doc);
                 let targetContext = undefined;
@@ -315,7 +315,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
             }
         }
         let search = false;
-        if (this.props.Document._searchDoc !== undefined) {
+        if (this.props.Document._searchDoc) {
             search = true;
         }
 
@@ -900,7 +900,7 @@ export class CollectionSchemaButtons extends CollectionSchemaCell {
         //     (!this.props.CollectionView || !this.props.CollectionView.props.isSelected() ? undefined :
         //         SetupDrag(reference, () => this._document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e));
         // };
-        return !BoolCast(this.props.Document._searchDoc) ? <></>
+        return !this.props.Document._searchDoc ? <></>
             : [DocumentType.PDF, DocumentType.RTF].includes(StrCast(doc.type) as DocumentType) ?
                 <div style={{ paddingTop: 8, paddingLeft: 3, }} >
                     <button style={{ padding: 2, left: 77 }} onClick={() => searchMatch(true)}>
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index 34a8bfa24..a90d78a87 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -287,12 +287,10 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
                 const colpos = this._searchTerm.indexOf(":");
                 const temp = this._searchTerm.slice(colpos + 1, this._searchTerm.length);
                 if (temp === "") {
-                    console.log("here we are first");
                     Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, undefined);
                     this.updateFilter();
                 }
                 else {
-                    console.log("here we are first");
                     Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, undefined);
                     this.tempfilter = temp;
                     Doc.setDocFilter(this.props.Document, this._key, temp, "check");
@@ -304,8 +302,8 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
                 Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, undefined);
                 this.updateFilter();
                 let keyOptions = this._searchTerm === "" ? this.props.possibleKeys : this.props.possibleKeys.filter(key => key.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1);
-                const blockedkeys = ["system", "ACL-Public", "_scrollTop", "customTitle", "limitHeight", "proto", "x", "y", "_width", "_height", "_autoHeight", "_fontSize", "_fontFamily", "context", "zIndex", "_timeStampOnEnter", "lines", "highlighting", "searchMatch", "creationDate", "isPrototype", "text-annotations", "aliases", "text-lastModified", "text-noTemplate", "layoutKey", "baseProto", "_xMargin", "_yMargin", "layout", "layout_keyValue", "links"];
-                keyOptions = keyOptions.filter(n => !blockedkeys.includes(n));
+                const blockedkeys = ["system", "customTitle", "limitHeight", "proto", "x", "y", "zIndex", "isPrototype", "text-annotations", "aliases", "text-lastModified", "text-noTemplate", "layoutKey", "baseProto", "layout", "layout_keyValue", "links"];
+                keyOptions = keyOptions.filter(n => !blockedkeys.includes(n) && !n.startsWith("_") && !n.startsWith("ACL"));
                 if (keyOptions.length) {
                     this.onSelect(keyOptions[0]);
                 } else if (this._searchTerm !== "" && this.props.canAddNew) {
@@ -338,8 +336,8 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
         const exactFound = keyOptions.findIndex(key => key.toUpperCase() === this._searchTerm.toUpperCase()) > -1 ||
             this.props.existingKeys.findIndex(key => key.toUpperCase() === this._searchTerm.toUpperCase()) > -1;
 
-        const blockedkeys = ["proto", "x", "y", "_width", "_height", "_autoHeight", "_fontSize", "_fontFamily", "context", "zIndex", "_timeStampOnEnter", "lines", "highlighting", "searchMatch", "creationDate", "isPrototype", "text-annotations", "aliases", "text-lastModified", "text-noTemplate", "layoutKey", "baseProto", "_xMargin", "_yMargin", "layout", "layout_keyValue", "links"];
-        keyOptions = keyOptions.filter(n => !blockedkeys.includes(n));
+        const blockedkeys = ["proto", "x", "y", "zIndex", "_timeStampOnEnter", "isPrototype", "text-annotations", "aliases", "text-lastModified", "text-noTemplate", "layoutKey", "baseProto", "layout", "layout_keyValue", "links"];
+        keyOptions = keyOptions.filter(n => !blockedkeys.includes(n) && !n.startsWith("_") && !n.startsWith("ACL"));
 
         const options = keyOptions.map(key => {
             return <div key={key} className="key-option" style={{
@@ -498,11 +496,7 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
             }
         });
 
-        keyOptions.forEach(key => {
-            Doc.setDocFilter(this.props.Document, this._key, key, undefined);
-        }
-        );
-        Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, undefined);
+        Doc.setDocFilter(this.props.Document, this._key, "", "remove");
         this.props.col.setColor("rgb(241, 239, 235)");
         this.closeResultsVisibility = "none";
     }
@@ -518,13 +512,9 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
                 <div className="keys-dropdown" style={{ zIndex: 1, width: this.props.width, maxWidth: this.props.width }}>
                     <input className="keys-search" style={{ width: "100%" }}
                         ref={this._inputRef} type="text" value={this._searchTerm} placeholder="Column key" onKeyDown={this.onKeyDown}
-                        onChange={e => {
-                            this.onChange(e.target.value);
-                        }}
-                        onClick={(e) => {
-                            //this._inputRef.current!.select();
-                            e.stopPropagation();
-                        }} onFocus={this.onFocus} ></input>
+                        onChange={e => this.onChange(e.target.value)}
+                        onClick={(e) => { e.stopPropagation(); this._inputRef.current?.focus(); }}
+                        onFocus={this.onFocus} ></input>
                     <div style={{ display: this.closeResultsVisibility }}>
                         <FontAwesomeIcon onPointerDown={this.removeFilters} icon={"times-circle"} size="lg"
                             style={{ cursor: "hand", color: "grey", padding: 2, left: -20, top: -1, height: 15, position: "relative" }} />
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index fc5dffaec..49d9a5c68 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -99,6 +99,9 @@
         direction: ltr;
         overflow: visible;
     }
+    .rt-noData {
+        display: none;
+    }
 
     .rt-thead {
         width: 100%;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 257099783..a78061da6 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -9,7 +9,7 @@ import { Resize } from "react-table";
 import "react-table/react-table.css";
 import { Doc, Opt } from "../../../fields/Doc";
 import { List } from "../../../fields/List";
-import { listSpec } from "../../../fields/Schema";
+import { listSpec, makeInterface, emptySchema } from "../../../fields/Schema";
 import { PastelSchemaPalette, SchemaHeaderField } from "../../../fields/SchemaHeaderField";
 import { Cast, NumCast, BoolCast } from "../../../fields/Types";
 import { TraceMobx } from "../../../fields/util";
@@ -73,7 +73,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @computed get menuCoordinates() {
         let searchx = 0;
         let searchy = 0;
-        if (this.props.Document._searchDoc !== undefined) {
+        if (this.props.Document._searchDoc) {
             const el = document.getElementsByClassName("collectionSchemaView-searchContainer")[0];
             if (el !== undefined) {
                 const rect = el.getBoundingClientRect();
@@ -305,17 +305,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                     this.columns = columns;
                     if (filter) {
                         Doc.setDocFilter(this.props.Document, newKey, filter, "match");
-                        if (this.props.Document.selectedDoc !== undefined) {
-                            const doc = Cast(this.props.Document.selectedDoc, Doc) as Doc;
-                            Doc.setDocFilter(doc, newKey, filter, "match");
-                        }
                     }
                     else {
                         this.props.Document._docFilters = undefined;
-                        if (this.props.Document.selectedDoc !== undefined) {
-                            const doc = Cast(this.props.Document.selectedDoc, Doc, null);
-                            doc._docFilters = undefined;
-                        }
                     }
                 }
             }
@@ -454,6 +446,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                     PanelHeight={this.previewHeight}
                     ScreenToLocalTransform={this.getPreviewTransform}
                     docFilters={this.docFilters}
+                    searchFilterDocs={this.searchFilterDocs}
                     ContainingCollectionDoc={this.props.CollectionView?.props.Document}
                     ContainingCollectionView={this.props.CollectionView}
                     moveDocument={this.props.moveDocument}
@@ -592,7 +585,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     }
     render() {
         let name = "collectionSchemaView-container";
-        if (this.props.Document._searchDoc !== undefined) {
+        if (this.props.Document._searchDoc) {
             name = "collectionSchemaView-searchContainer";
         }
         if (!this.props.active()) setTimeout(() => this.closeHeader(), 0);
@@ -615,7 +608,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         return <div className={name}
             style={{
                 overflow: this.props.overflow === true ? "scroll" : undefined, backgroundColor: "white",
-                pointerEvents: !this.props.active() && !SnappingManager.GetIsDragging() ? "none" : undefined,
+                pointerEvents: this.props.Document._searchDoc !== undefined && !this.props.active() && !SnappingManager.GetIsDragging() ? "none" : undefined,
                 width: name === "collectionSchemaView-searchContainer" ? "auto" : this.props.PanelWidth() || "100%", height: this.props.PanelHeight() || "100%", position: "relative",
             }}  >
             <div className="collectionSchemaView-tableContainer"
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index a9437c11f..a50dab54d 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -217,6 +217,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument)
             opacity={opacity}
             focus={this.focusDocument}
             docFilters={this.docFilters}
+            searchFilterDocs={this.searchFilterDocs}
             ContainingCollectionDoc={this.props.CollectionView?.props.Document}
             ContainingCollectionView={this.props.CollectionView}
             addDocument={this.props.addDocument}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index a1dd905c2..c73159084 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -111,6 +111,9 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
             return this.props.ignoreFields?.includes("_docFilters") ? [] :
                 [...this.props.docFilters(), ...Cast(this.props.Document._docFilters, listSpec("string"), [])];
         }
+        searchFilterDocs = () => {
+            return [...this.props.searchFilterDocs(), ...DocListCast(this.props.Document._searchFilterDocs)];
+        }
         @computed get childDocs() {
             let rawdocs: (Doc | Promise<Doc>)[] = [];
             if (this.dataField instanceof Doc) { // if collection data is just a document, then promote it to a singleton list;
@@ -128,34 +131,31 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
             const viewSpecScript = Cast(this.props.Document.viewSpecScript, ScriptField);
             const childDocs = viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs;
 
-            let searchDocs = DocListCast(this.props.Document._searchDocs);
-
+            let searchDocs = this.searchFilterDocs();
 
             let docsforFilter: Doc[] = childDocs;
 
-            if (searchDocs !== undefined && searchDocs.length > 0) {
+            if (searchDocs.length > 0) {
                 docsforFilter = [];
                 const docRangeFilters = this.props.ignoreFields?.includes("_docRangeFilters") ? [] : Cast(this.props.Document._docRangeFilters, listSpec("string"), []);
-                console.log(searchDocs);
                 searchDocs = DocUtils.FilterDocs(searchDocs, this.docFilters(), docRangeFilters, viewSpecScript);
                 childDocs.forEach((d) => {
+                    let notFiltered = searchDocs.includes(d) || d.z;
                     if (d.data !== undefined) {
-                        let newdocs = DocListCast(d.data);
-                        if (newdocs.length > 0) {
-                            let displaycheck = false;
+                        let subDocs = DocListCast(d.data);
+                        if (subDocs.length > 0) {
                             let newarray: Doc[] = [];
-                            while (newdocs.length > 0) {
+                            while (subDocs.length > 0 && !notFiltered) {
                                 newarray = [];
-                                newdocs.forEach((t) => {
+                                subDocs.forEach((t) => {
+                                    notFiltered = notFiltered || searchDocs.includes(t);
                                     DocListCast(t.data).forEach((newdoc) => newarray.push(newdoc));
-                                    displaycheck = displaycheck || searchDocs.includes(t);
                                 });
-                                newdocs = newarray;
+                                subDocs = newarray;
                             }
-                            displaycheck && docsforFilter.push(d);
                         }
                     }
-                    searchDocs.includes(d) && docsforFilter.push(d);
+                    notFiltered && docsforFilter.push(d);
                 });
                 return docsforFilter;
             }
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 8440d3e9b..9460095e4 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -8,7 +8,7 @@ import { PrefetchProxy } from '../../../fields/Proxy';
 import { Document, listSpec } from '../../../fields/Schema';
 import { ComputedField, ScriptField } from '../../../fields/ScriptField';
 import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
-import { emptyFunction, emptyPath, returnFalse, returnOne, returnTrue, returnZero, simulateMouseClick, Utils, returnEmptyFilter } from '../../../Utils';
+import { emptyFunction, emptyPath, returnFalse, returnOne, returnTrue, returnZero, simulateMouseClick, Utils, returnEmptyFilter, returnEmptyDoclist } from '../../../Utils';
 import { Docs, DocUtils } from '../../documents/Documents';
 import { DocumentType } from "../../documents/DocumentTypes";
 import { DocumentManager } from '../../util/DocumentManager';
@@ -359,6 +359,7 @@ class TreeView extends React.Component<TreeViewProps> {
                     focus={returnFalse}
                     ScreenToLocalTransform={this.docTransform}
                     docFilters={returnEmptyFilter}
+                    searchFilterDocs={returnEmptyDoclist}
                     ContainingCollectionDoc={this.props.containingCollection}
                     ContainingCollectionView={undefined}
                     addDocument={returnFalse}
@@ -466,6 +467,7 @@ class TreeView extends React.Component<TreeViewProps> {
                 bringToFront={emptyFunction}
                 dontRegisterView={BoolCast(this.props.treeViewDoc.dontRegisterChildViews)}
                 docFilters={returnEmptyFilter}
+                searchFilterDocs={returnEmptyDoclist}
                 ContainingCollectionView={undefined}
                 ContainingCollectionDoc={this.props.containingCollection}
             />;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index ca3b67610..5230fb533 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -18,7 +18,7 @@ import { ComputedField, ScriptField } from '../../../fields/ScriptField';
 import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { ImageField } from '../../../fields/URLField';
 import { TraceMobx, GetEffectiveAcl, SharingPermissions, distributeAcls } from '../../../fields/util';
-import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils';
+import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils, returnEmptyDoclist } from '../../../Utils';
 import { Docs, DocUtils } from '../../documents/Documents';
 import { DocumentType } from '../../documents/DocumentTypes';
 import { CurrentUserUtils } from '../../util/CurrentUserUtils';
@@ -537,6 +537,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                     fieldKey={`${this.props.fieldKey}-filter`}
                     CollectionView={this}
                     docFilters={returnEmptyFilter}
+                    searchFilterDocs={returnEmptyDoclist}
                     ContainingCollectionDoc={this.props.ContainingCollectionDoc}
                     ContainingCollectionView={this.props.ContainingCollectionView}
                     PanelWidth={this.facetWidth}
diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx
index 6ec9783e2..e1c81aeab 100644
--- a/src/client/views/collections/SchemaTable.tsx
+++ b/src/client/views/collections/SchemaTable.tsx
@@ -12,7 +12,7 @@ import { listSpec } from "../../../fields/Schema";
 import { SchemaHeaderField } from "../../../fields/SchemaHeaderField";
 import { ComputedField } from "../../../fields/ScriptField";
 import { Cast, FieldValue, NumCast, StrCast } from "../../../fields/Types";
-import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero } from "../../../Utils";
+import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero, returnEmptyDoclist } from "../../../Utils";
 import { Docs, DocumentOptions } from "../../documents/Documents";
 import { DocumentType } from "../../documents/DocumentTypes";
 import { CompileScript, Transformer, ts } from "../../util/Scripting";
@@ -627,6 +627,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                         PanelHeight={() => 150}
                         ScreenToLocalTransform={this.getPreviewTransform}
                         docFilters={returnEmptyFilter}
+                        searchFilterDocs={returnEmptyDoclist}
                         ContainingCollectionDoc={this.props.CollectionView?.props.Document}
                         ContainingCollectionView={this.props.CollectionView}
                         moveDocument={this.props.moveDocument}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index e66e469eb..0c0f6ca58 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -974,6 +974,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             ContainingCollectionView: this.props.CollectionView,
             ContainingCollectionDoc: this.props.Document,
             docFilters: this.docFilters,
+            searchFilterDocs: this.searchFilterDocs,
             focus: this.focusDocument,
             backgroundColor: this.getClusterColor,
             backgroundHalo: this.backgroundHalo,
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index fb138ecc0..cbce6448f 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -8,7 +8,7 @@ import { EditableView } from "../../EditableView";
 import { KeyValueBox } from "../../nodes/KeyValueBox";
 import { Cast, NumCast, StrCast } from "../../../../fields/Types";
 import { ContentFittingDocumentView } from "../../nodes/ContentFittingDocumentView";
-import { returnFalse, returnOne, emptyFunction, emptyPath, returnTrue, returnZero, returnEmptyFilter, Utils } from "../../../../Utils";
+import { returnFalse, returnOne, emptyFunction, emptyPath, returnTrue, returnZero, returnEmptyFilter, Utils, returnEmptyDoclist } from "../../../../Utils";
 import { Id } from "../../../../fields/FieldSymbols";
 import { Transform } from "../../../util/Transform";
 import { PropertiesButtons } from "../../PropertiesButtons";
@@ -284,6 +284,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     focus={returnFalse}
                     ScreenToLocalTransform={this.getTransform}
                     docFilters={returnEmptyFilter}
+                    searchFilterDocs={returnEmptyDoclist}
                     ContainingCollectionDoc={undefined}
                     ContainingCollectionView={undefined}
                     addDocument={returnFalse}
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index 21d283547..0afcab5a3 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -234,6 +234,7 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
             ScreenToLocalTransform={dxf}
             focus={this.props.focus}
             docFilters={this.docFilters}
+            searchFilterDocs={this.searchFilterDocs}
             ContainingCollectionDoc={this.props.CollectionView?.props.Document}
             ContainingCollectionView={this.props.CollectionView}
             addDocument={this.props.addDocument}
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index d02088a6c..53825eece 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -234,6 +234,7 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
             ScreenToLocalTransform={dxf}
             focus={this.props.focus}
             docFilters={this.docFilters}
+            searchFilterDocs={this.searchFilterDocs}
             ContainingCollectionDoc={this.props.CollectionView?.props.Document}
             ContainingCollectionView={this.props.CollectionView}
             addDocument={this.props.addDocument}
diff --git a/src/client/views/nodes/DocHolderBox.tsx b/src/client/views/nodes/DocHolderBox.tsx
index 88eb48f51..b3b7cc4f3 100644
--- a/src/client/views/nodes/DocHolderBox.tsx
+++ b/src/client/views/nodes/DocHolderBox.tsx
@@ -120,6 +120,7 @@ export class DocHolderBox extends ViewBoxAnnotatableComponent<FieldViewProps, Do
                     DataDoc={undefined}
                     LibraryPath={emptyPath}
                     docFilters={this.props.docFilters}
+                    searchFilterDocs={this.props.searchFilterDocs}
                     ContainingCollectionView={this as any} // bcz: hack!  need to pass a prop that can be used to select the container (ie, 'this') when the up selector in document decorations is clicked.  currently, the up selector allows only a containing collection to be selected
                     ContainingCollectionDoc={undefined}
                     fitToBox={true}
@@ -149,6 +150,7 @@ export class DocHolderBox extends ViewBoxAnnotatableComponent<FieldViewProps, Do
                     DataDoc={undefined}
                     LibraryPath={emptyPath}
                     docFilters={this.props.docFilters}
+                    searchFilterDocs={this.props.searchFilterDocs}
                     ContainingCollectionView={this as any} // bcz: hack!  need to pass a prop that can be used to select the container (ie, 'this') when the up selector in document decorations is clicked.  currently, the up selector allows only a containing collection to be selected
                     ContainingCollectionDoc={undefined}
                     fitToBox={true}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 91f12f004..bf42f30fe 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -45,6 +45,7 @@ export interface DocumentViewProps {
     ContainingCollectionView: Opt<CollectionView>;
     ContainingCollectionDoc: Opt<Doc>;
     docFilters: () => string[];
+    searchFilterDocs: () => Doc[];
     FreezeDimensions?: boolean;
     NativeWidth: () => number;
     NativeHeight: () => number;
@@ -829,6 +830,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         return (<div className="documentView-contentsView" style={{ borderRadius: "inherit", width: "100%", height: "100%" }}>
             <DocumentContentsView key={1}
                 docFilters={this.props.docFilters}
+                searchFilterDocs={this.props.searchFilterDocs}
                 ContainingCollectionView={this.props.ContainingCollectionView}
                 ContainingCollectionDoc={this.props.ContainingCollectionDoc}
                 NativeWidth={this.NativeWidth}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 3726f1d5f..fceeced36 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -29,6 +29,7 @@ export interface FieldViewProps {
     dropAction: dropActionType;
     backgroundHalo?: () => boolean;
     docFilters: () => string[];
+    searchFilterDocs: () => Doc[];
     isSelected: (outsideReaction?: boolean) => boolean;
     select: (isCtrlPressed: boolean) => void;
     rootSelected: (outsideReaction?: boolean) => boolean;
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 216c5f39e..dd3914df7 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -489,6 +489,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps, ImageD
                 ScreenToLocalTransform={this.screenToLocalTransform}
                 renderDepth={this.props.renderDepth + 1}
                 docFilters={this.props.docFilters}
+                searchFilterDocs={this.props.searchFilterDocs}
                 ContainingCollectionDoc={this.props.ContainingCollectionDoc}>
                 {this.contentFunc}
             </CollectionFreeFormView>
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index c4481b213..f154c5f56 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -3,7 +3,7 @@ import { observer } from "mobx-react";
 import wiki from "wikijs";
 import { Doc, DocCastAsync, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
 import { Cast, FieldValue, NumCast } from "../../../fields/Types";
-import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero } from "../../../Utils";
+import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero, returnEmptyDoclist } from "../../../Utils";
 import { Docs } from "../../documents/Documents";
 import { DocumentManager } from "../../util/DocumentManager";
 import { Transform } from "../../util/Transform";
@@ -101,6 +101,7 @@ export class LinkDocPreview extends React.Component<Props> {
                 pinToPres={returnFalse}
                 dontRegisterView={true}
                 docFilters={returnEmptyFilter}
+                searchFilterDocs={returnEmptyDoclist}
                 ContainingCollectionDoc={undefined}
                 ContainingCollectionView={undefined}
                 renderDepth={0}
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 255a1b2d0..890263a61 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -246,7 +246,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
             <PDFViewer {...this.props} pdf={this._pdf!} url={pdfUrl!.url.pathname} active={this.props.active} loaded={this.loaded}
                 setPdfViewer={this.setPdfViewer} ContainingCollectionView={this.props.ContainingCollectionView}
                 renderDepth={this.props.renderDepth} PanelHeight={this.props.PanelHeight} PanelWidth={this.props.PanelWidth}
-                addDocTab={this.props.addDocTab} focus={this.props.focus} docFilters={this.props.docFilters}
+                addDocTab={this.props.addDocTab} focus={this.props.focus} docFilters={this.props.docFilters} searchFilterDocs={this.props.searchFilterDocs}
                 pinToPres={this.props.pinToPres} addDocument={this.addDocument}
                 Document={this.props.Document} DataDoc={this.dataDoc} ContentScaling={this.props.ContentScaling}
                 ScreenToLocalTransform={this.props.ScreenToLocalTransform} select={this.props.select}
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index ee92e517c..dd76503d5 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -384,6 +384,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
                     ScreenToLocalTransform={this.props.ScreenToLocalTransform}
                     renderDepth={this.props.renderDepth + 1}
                     docFilters={this.props.docFilters}
+                    searchFilterDocs={this.props.searchFilterDocs}
                     ContainingCollectionDoc={this.props.ContainingCollectionDoc}>
                     {this.contentFunc}
                 </CollectionFreeFormView>
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 1393e7868..7d7426e31 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -733,6 +733,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
                             ScreenToLocalTransform={this.scrollXf}
                             renderDepth={this.props.renderDepth + 1}
                             docFilters={this.props.docFilters}
+                            searchFilterDocs={this.props.searchFilterDocs}
                             ContainingCollectionDoc={this.props.ContainingCollectionDoc}>
                         </CollectionFreeFormView>
                     </div>
diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx
index 31dd92b59..08bab8d12 100644
--- a/src/client/views/nodes/formattedText/DashDocView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocView.tsx
@@ -5,7 +5,7 @@ import { Id } from "../../../../fields/FieldSymbols";
 import { ObjectField } from "../../../../fields/ObjectField";
 import { ComputedField } from "../../../../fields/ScriptField";
 import { BoolCast, Cast, NumCast, StrCast } from "../../../../fields/Types";
-import { emptyFunction, returnEmptyString, returnFalse, Utils, returnZero, returnEmptyFilter } from "../../../../Utils";
+import { emptyFunction, returnEmptyString, returnFalse, Utils, returnZero, returnEmptyFilter, returnEmptyDoclist } from "../../../../Utils";
 import { DocServer } from "../../../DocServer";
 import { Docs, DocUtils } from "../../../documents/Documents";
 import { DocumentView } from "../DocumentView";
@@ -255,6 +255,7 @@ export class DashDocView extends React.Component<IDashDocView> {
                             bringToFront={emptyFunction}
                             dontRegisterView={false}
                             docFilters={this.props.tbox?.props.docFilters || returnEmptyFilter}
+                            searchFilterDocs={this.props.tbox?.props.searchFilterDocs || returnEmptyDoclist}
                             ContainingCollectionView={this._textBox.props.ContainingCollectionView}
                             ContainingCollectionDoc={this._textBox.props.ContainingCollectionDoc}
                             ContentScaling={this.contentScaling}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index 6f3984f39..1e1bcd42c 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -4,7 +4,7 @@ import { EditorView } from "prosemirror-view";
 import * as ReactDOM from 'react-dom';
 import { Doc, DocCastAsync, Opt } from "../../../../fields/Doc";
 import { Cast, FieldValue, NumCast, StrCast } from "../../../../fields/Types";
-import { emptyFunction, returnEmptyString, returnFalse, Utils, emptyPath, returnZero, returnOne, returnEmptyFilter } from "../../../../Utils";
+import { emptyFunction, returnEmptyString, returnFalse, Utils, emptyPath, returnZero, returnOne, returnEmptyFilter, returnEmptyDoclist } from "../../../../Utils";
 import { DocServer } from "../../../DocServer";
 import { DocumentManager } from "../../../util/DocumentManager";
 import { schema } from "./schema_rts";
@@ -302,6 +302,7 @@ export class FormattedTextBoxComment {
                                             pinToPres={returnFalse}
                                             dontRegisterView={true}
                                             docFilters={returnEmptyFilter}
+                                            searchFilterDocs={returnEmptyDoclist}
                                             ContainingCollectionDoc={undefined}
                                             ContainingCollectionView={undefined}
                                             renderDepth={0}
diff --git a/src/client/views/nodes/formattedText/RichTextSchema.tsx b/src/client/views/nodes/formattedText/RichTextSchema.tsx
index a85dacc7e..b76e520b7 100644
--- a/src/client/views/nodes/formattedText/RichTextSchema.tsx
+++ b/src/client/views/nodes/formattedText/RichTextSchema.tsx
@@ -155,6 +155,7 @@ export class DashDocView {
                     bringToFront={emptyFunction}
                     dontRegisterView={false}
                     docFilters={this._textBox.props.docFilters}
+                    searchFilterDocs={this._textBox.props.searchFilterDocs}
                     ContainingCollectionView={this._textBox.props.ContainingCollectionView}
                     ContainingCollectionDoc={this._textBox.props.ContainingCollectionDoc}
                     ContentScaling={this.contentScaling}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index f2aa9fa3f..67d435194 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -56,6 +56,7 @@ interface IViewerProps {
     Document: Doc;
     DataDoc?: Doc;
     docFilters: () => string[];
+    searchFilterDocs: () => Doc[];
     ContainingCollectionView: Opt<CollectionView>;
     PanelWidth: () => number;
     PanelHeight: () => number;
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index a25a8ee33..dfcf575f1 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -102,6 +102,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
                     bringToFront={returnFalse}
                     opacity={returnOne}
                     docFilters={this.props.docFilters}
+                    searchFilterDocs={this.props.searchFilterDocs}
                     ContainingCollectionView={undefined}
                     ContainingCollectionDoc={undefined}
                     ContentScaling={returnOne}
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index c571adefe..9c9900bfb 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -1,6 +1,6 @@
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { Tooltip } from '@material-ui/core';
-import { action, computed, IReactionDisposer, observable, runInAction } from 'mobx';
+import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, DocListCast, Field, Opt } from '../../../fields/Doc';
@@ -17,8 +17,8 @@ import { SetupDrag } from '../../util/DragManager';
 import { SearchUtil } from '../../util/SearchUtil';
 import { SelectionManager } from '../../util/SelectionManager';
 import { Transform } from '../../util/Transform';
-import { ColumnType } from "../collections/CollectionSchemaView";
-import { CollectionView, CollectionViewType } from '../collections/CollectionView';
+import { CollectionSchemaView, ColumnType } from "../collections/CollectionSchemaView";
+import { CollectionViewType } from '../collections/CollectionView';
 import { ViewBoxBaseComponent } from "../DocComponent";
 import { DocumentView } from '../nodes/DocumentView';
 import { FieldView, FieldViewProps } from '../nodes/FieldView';
@@ -46,11 +46,11 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
     private _disposers: { [name: string]: IReactionDisposer } = {};
     private _blockedTypes = [DocumentType.PRESELEMENT, DocumentType.KVP, DocumentType.DOCHOLDER, DocumentType.SEARCH, DocumentType.SEARCHITEM, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING];
 
-    private currentSelectedCollection: DocumentView | undefined = undefined;
-    private docsforfilter: Doc[] = [];
+    private docsforfilter: Doc[] | undefined = [];
     private realTotalResults: number = 0;
     private collectionRef = React.createRef<HTMLSpanElement>();
 
+    @observable _currentSelectedCollection: DocumentView | undefined = undefined;
     @observable _icons: string[] = this._allIcons;
     @observable _results: [Doc, string[], string[]][] = [];
     @observable _visibleElements: JSX.Element[] = [];
@@ -64,9 +64,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
     @observable open = false;
     @observable children = 0;
     @observable newsearchstring = "";
-    @observable headercount: number = 0;
-    @observable headerscale: number = 0;
-    @observable filter = false;
+    @computed get filter() { return this._results?.length && (this._currentSelectedCollection?.props.Document._searchFilterDocs || this._currentSelectedCollection?.props.Document._docFilters); }
 
     constructor(props: any) {
         super(props);
@@ -78,6 +76,8 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
             this._inputRef.current.focus();
             this._searchbarOpen = true;
         }
+        this._disposers.filters = reaction(() => this.props.Document._docFilters,
+            (filters: any) => this.setSearchFilter(this._currentSelectedCollection, this.filter ? undefined : this.docsforfilter));
     });
 
     componentWillUnmount() {
@@ -89,14 +89,12 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
         this.layoutDoc._searchString = e.target.value;
         this.newsearchstring = e.target.value;
         if (e.target.value === "") {
-            if (this.currentSelectedCollection) {
-                this.setSearchDocsRecursive(this.currentSelectedCollection, undefined);
-            }
-            this.closeSearch(false);
+            this.docsforfilter = undefined;
+            this.setSearchFilter(this._currentSelectedCollection, undefined);
+            this.resetSearch(false);
 
-            if (this.currentSelectedCollection !== undefined) {
-                this.currentSelectedCollection = undefined;
-                this.props.Document.selectedDoc = undefined;
+            if (this._currentSelectedCollection !== undefined) {
+                this._currentSelectedCollection = undefined;
             }
             this.open = false;
             this._results = [];
@@ -226,10 +224,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
         query = query.toLowerCase();
 
         if (selectedCollection !== undefined) {
-            this.currentSelectedCollection = selectedCollection;
-            if (this.filter === true) {
-                this.props.Document.selectedDoc = selectedCollection.props.Document;
-            }
+            this._currentSelectedCollection = selectedCollection;
             let docs = DocListCast(selectedCollection.dataDoc[Doc.LayoutFieldKey(selectedCollection.dataDoc)]);
             const found: [Doc, string[], string[]][] = [];
             const docsforFilter: Doc[] = [];
@@ -251,10 +246,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
             }
             this._results = found;
             this.docsforfilter = docsforFilter;
-            if (this.filter === true) {
-                selectedCollection.props.Document._searchDocs = new List<Doc>(docsforFilter);
-                this.setSearchDocsRecursive(selectedCollection, docsforFilter);
-            }
+            this.setSearchFilter(selectedCollection, this.filter && found.length ? docsforFilter : undefined);
             this._numTotalResults = found.length;
             this.realTotalResults = found.length;
         }
@@ -277,23 +269,17 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
     }
 
     @action
-    submitSearch = async (reset?: boolean) => {
-        if (this.currentSelectedCollection !== undefined) {
-            this.setSearchDocsRecursive(this.currentSelectedCollection, undefined);
-        }
-        if (reset) {
-            this.layoutDoc._searchString = "";
-        }
+    submitSearch = async () => {
+        this.resetSearch(false);
+
         //this.props.Document._docFilters = new List();
         this._noResults = "";
 
         this.dataDoc[this.fieldKey] = new List<Doc>([]);
-        this.headercount = 0;
         this.children = 0;
         let query = StrCast(this.layoutDoc._searchString);
         Doc.SetSearchQuery(query);
-        this._searchFullDB ? query = this.getFinalQuery(query) : console.log("local");
-        this.closeSearch(false);
+        this._searchFullDB && (query = this.getFinalQuery(query));
         this._results = [];
         this._resultsSet.clear();
         this._visibleElements = [];
@@ -425,12 +411,14 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
     }
 
     @action.bound
-    closeSearch = (closesearchbar = true) => {
+    resetSearch = (close: boolean) => {
         this._results.forEach(result => {
             Doc.UnBrushDoc(result[0]);
             Doc.ClearSearchMatches();
         });
-        closesearchbar && (this._searchbarOpen = false);
+        if (close) {
+            this._searchbarOpen = false;
+        }
     }
 
     @action.bound
@@ -482,7 +470,6 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
                 }
             }
         }
-        this.headerscale = headers.size;
         const oldSchemaHeaders = Cast(this.props.Document._schemaHeaders, listSpec("string"), []);
         if (oldSchemaHeaders?.length && typeof oldSchemaHeaders[0] !== "object") {
             const newSchemaHeaders = oldSchemaHeaders.map(i => typeof i === "string" ? new SchemaHeaderField(i, "#f1efeb") : i);
@@ -491,7 +478,6 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
                     newSchemaHeaders.push(new SchemaHeaderField(header, "#f1efeb"));
                 }
             });
-            this.headercount = newSchemaHeaders.length;
             this.props.Document._schemaHeaders = new List<SchemaHeaderField>(newSchemaHeaders);
         } else if (this.props.Document._schemaHeaders === undefined) {
             this.props.Document._schemaHeaders = new List<SchemaHeaderField>([new SchemaHeaderField("title", "#f1efeb")]);
@@ -518,12 +504,10 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
 
     @action
     changeSearchScope = (scope: string) => {
-        scope && (this.filter = false);
+        this.docsforfilter = undefined;
+        this.setSearchFilter(this._currentSelectedCollection, undefined);
         this._searchFullDB = scope;
         this.dataDoc[this.fieldKey] = new List<Doc>([]);
-        if (this.currentSelectedCollection !== undefined) {
-            this.setSearchDocsRecursive(this.currentSelectedCollection, undefined);
-        }
         this.submitSearch();
     }
 
@@ -558,28 +542,14 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
         </div>;
     }
 
-    setSearchDocsRecursive = (collectionView: DocumentView, filter: Doc[] | undefined) => {
-        let docs = DocListCast(collectionView.dataDoc[Doc.LayoutFieldKey(collectionView.dataDoc)]);
-        let newarray: Doc[] = [];
-        while (docs.length > 0) {
-            newarray = [];
-            docs.forEach(d => {
-                const subDocs = DocListCast(d.data);
-                if (subDocs.length) {
-                    d._searchDocs = filter ? new List<Doc>(filter) : undefined;
-                    DocListCast(d.data).forEach(newdoc => newarray.push(newdoc));
-                }
-            });
-            docs = newarray;
+    setSearchFilter = (collectionView: DocumentView | undefined, docsForFilter: Doc[] | undefined) => {
+        if (collectionView) {
+            const docFilters = Cast(this.props.Document._docFilters, listSpec("string"), null);
+            collectionView.props.Document._searchFilterDocs = docsForFilter?.length ? new List<Doc>(docsForFilter) : undefined;
+            collectionView.props.Document._docFilters = docsForFilter?.length && docFilters?.length ? new List<string>(docFilters) : undefined;
         }
-        collectionView.props.Document._searchDocs = filter ? new List<Doc>(filter) : undefined;
-        this.props.Document.selectedDoc = filter ? collectionView.props.Document : undefined;
     }
-
     render() {
-        this.props.Document._chromeStatus === "disabled";
-        this.props.Document._searchDoc = true;
-        const rows = this.children;
         return (
             <div style={{ pointerEvents: "all" }} className="searchBox-container">
                 <div style={{ position: "absolute", left: 15, height: 32, alignItems: "center", display: "flex" }}>{`${Doc.CurrentUserEmail}/${Cast(Doc.UserDoc().activeDashboard, Doc, null)?.title}`}</div>
@@ -604,34 +574,34 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
                                         <FontAwesomeIcon icon={"filter"} size="lg"
                                             style={{ cursor: "hand", padding: 1, backgroundColor: this.filter ? "white" : "lightgray", color: this.filter ? "black" : "white" }}
                                             onPointerDown={e => { e.stopPropagation(); SetupDrag(this.collectionRef, () => this.layoutDoc._searchString ? this.startDragCollection() : undefined); }}
-                                            onClick={action(() => {
-                                                this.filter = !this.filter && !this._searchFullDB;
-                                                this.currentSelectedCollection && this.setSearchDocsRecursive(this.currentSelectedCollection, this.filter ? this.docsforfilter : undefined);
-                                            })} />
+                                            onClick={action(() => this.setSearchFilter(this._currentSelectedCollection, this.filter ? undefined : this.docsforfilter))} />
                                     </div>
                                 </Tooltip>
                             </div>
                             {this.scopeButtons}
                         </div>
-
                     </div >
                 </div >
-                {!this._searchbarOpen ? (null) : <div style={{ zIndex: 20000, color: "black" }}>
-                    <div style={{ display: "flex", justifyContent: "center", }}>
-                        <div style={{ display: this.open ? "flex" : "none", overflow: "auto", }}>
-                            <CollectionView {...this.props}
-                                Document={this.props.Document}
-                                moveDocument={returnFalse}
-                                removeDocument={returnFalse}
-                                PanelHeight={this.open ? this.returnHeight : returnZero}
-                                PanelWidth={this.open ? this.returnLength : returnZero}
-                                overflow={length > window.innerWidth || rows > 6 ? true : false}
-                                focus={this.selectElement}
-                                ScreenToLocalTransform={Transform.Identity}
-                            />
+                {!this._searchbarOpen ? (null) :
+                    <div style={{ zIndex: 20000, color: "black" }} ref={(r) => r?.focus()}>
+                        <div style={{ display: "flex", justifyContent: "center", }}>
+                            <div style={{ display: this.open ? "flex" : "none", overflow: "auto", }}>
+                                <CollectionSchemaView {...this.props}
+                                    CollectionView={undefined}
+                                    annotationsKey={""}
+                                    addDocument={returnFalse}
+                                    Document={this.props.Document}
+                                    moveDocument={returnFalse}
+                                    removeDocument={returnFalse}
+                                    PanelHeight={this.open ? this.returnHeight : returnZero}
+                                    PanelWidth={this.open ? this.returnLength : returnZero}
+                                    overflow={length > window.innerWidth || this.children > 6 ? true : false}
+                                    focus={this.selectElement}
+                                    ScreenToLocalTransform={Transform.Identity}
+                                />
+                            </div>
                         </div>
                     </div>
-                </div>
                 }
             </div >
         );
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index dc274a063..272b70293 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1024,10 +1024,10 @@ export namespace Doc {
         const fieldVal = doc[key];
         if (Cast(fieldVal, listSpec("string"), []).length) {
             const vals = Cast(fieldVal, listSpec("string"), []);
-            return vals.some(v => v === value);
+            return vals.some(v => v.includes(value));  // bcz: arghh: Todo: comparison should be parameterized as exact, or substring
         }
         const fieldStr = Field.toString(fieldVal as Field);
-        return fieldStr === value;
+        return fieldStr.includes(value); // bcz: arghh: Todo: comparison should be parameterized as exact, or substring
     }
 
     export function deiconifyView(doc: any) {
@@ -1056,18 +1056,14 @@ export namespace Doc {
         }
     }
 
-    export function aliasDocs(field: any) {
-        return new List<Doc>(field.map((d: any) => Doc.MakeAlias(d)));
-    }
-
     // filters document in a container collection:
     // all documents with the specified value for the specified key are included/excluded 
     // based on the modifiers :"check", "x", undefined
-    export function setDocFilter(container: Doc, key: string, value: any, modifiers?: "match" | "check" | "x" | undefined) {
+    export function setDocFilter(container: Doc, key: string, value: any, modifiers?: "remove" | "match" | "check" | "x" | undefined) {
         const docFilters = Cast(container._docFilters, listSpec("string"), []);
         runInAction(() => {
             for (let i = 0; i < docFilters.length; i += 3) {
-                if (docFilters[i] === key && (docFilters[i + 1] === value || modifiers === "match")) {
+                if (docFilters[i] === key && (docFilters[i + 1] === value || modifiers === "match" || modifiers === "remove")) {
                     if (docFilters[i + 2] === modifiers && modifiers && docFilters[i + 1] === value) return;
                     docFilters.splice(i, 3);
                     container._docFilters = new List<string>(docFilters);
@@ -1077,7 +1073,7 @@ export namespace Doc {
             if (typeof modifiers === "string") {
                 if (!docFilters.length && modifiers === "match" && value === undefined) {
                     container._docFilters = undefined;
-                } else {
+                } else if (modifiers !== "remove") {
                     docFilters.push(key);
                     docFilters.push(value);
                     docFilters.push(modifiers);
@@ -1274,7 +1270,6 @@ Scripting.addGlobal(function getDocTemplate(doc?: any) { return Doc.getDocTempla
 Scripting.addGlobal(function getAlias(doc: any) { return Doc.MakeAlias(doc); });
 Scripting.addGlobal(function getCopy(doc: any, copyProto: any) { return doc.isTemplateDoc ? Doc.ApplyTemplate(doc) : Doc.MakeCopy(doc, copyProto); });
 Scripting.addGlobal(function copyField(field: any) { return field instanceof ObjectField ? ObjectField.MakeCopy(field) : field; });
-Scripting.addGlobal(function aliasDocs(field: any) { return Doc.aliasDocs(field); });
 Scripting.addGlobal(function docList(field: any) { return DocListCast(field); });
 Scripting.addGlobal(function setInPlace(doc: any, field: any, value: any) { return Doc.SetInPlace(doc, field, value, false); });
 Scripting.addGlobal(function sameDocs(doc1: any, doc2: any) { return Doc.AreProtosEqual(doc1, doc2); });
diff --git a/src/fields/List.ts b/src/fields/List.ts
index a9da75abb..1c2b89b01 100644
--- a/src/fields/List.ts
+++ b/src/fields/List.ts
@@ -1,14 +1,16 @@
-import { Deserializable, autoObject, afterDocDeserialize } from "../client/util/SerializationHelper";
+import { action, observable, runInAction } from "mobx";
+import { alias, list, serializable } from "serializr";
+import { DocServer } from "../client/DocServer";
+import { Scripting } from "../client/util/Scripting";
+import { afterDocDeserialize, autoObject, Deserializable } from "../client/util/SerializationHelper";
 import { Field } from "./Doc";
-import { setter, getter, deleteProperty, updateFunction } from "./util";
-import { serializable, alias, list } from "serializr";
-import { observable, action, runInAction } from "mobx";
+import { Copy, OnUpdate, Parent, Self, SelfProxy, ToScriptString, ToString, Update } from "./FieldSymbols";
 import { ObjectField } from "./ObjectField";
-import { RefField } from "./RefField";
 import { ProxyField } from "./Proxy";
-import { Self, Update, Parent, OnUpdate, SelfProxy, ToScriptString, ToString, Copy, Id } from "./FieldSymbols";
-import { Scripting } from "../client/util/Scripting";
-import { DocServer } from "../client/DocServer";
+import { RefField } from "./RefField";
+import { listSpec } from "./Schema";
+import { Cast } from "./Types";
+import { deleteProperty, getter, setter, updateFunction } from "./util";
 
 const listHandlers: any = {
     /// Mutator methods
@@ -328,4 +330,9 @@ class ListImpl<T extends Field> extends ObjectField {
 export type List<T extends Field> = ListImpl<T> & (T | (T extends RefField ? Promise<T> : never))[];
 export const List: { new <T extends Field>(fields?: T[]): List<T> } = ListImpl as any;
 
-Scripting.addGlobal("List", List);
\ No newline at end of file
+Scripting.addGlobal("List", List);
+Scripting.addGlobal(function compareLists(l1: any, l2: any) {
+    const L1 = Cast(l1, listSpec("string"), []);
+    const L2 = Cast(l2, listSpec("string"), []);
+    return L1 && L2 && L1.length === L2.length && L2.reduce((p, v) => p && L1.includes(v), true);
+}, "compare two lists");
\ No newline at end of file
diff --git a/src/mobile/AudioUpload.tsx b/src/mobile/AudioUpload.tsx
index 8ae504f1b..738de09c6 100644
--- a/src/mobile/AudioUpload.tsx
+++ b/src/mobile/AudioUpload.tsx
@@ -3,7 +3,7 @@ import "./ImageUpload.scss";
 import React = require('react');
 import { observer } from 'mobx-react';
 import { observable, action, computed } from 'mobx';
-import { Utils, emptyPath, returnFalse, emptyFunction, returnOne, returnZero, returnTrue, returnEmptyFilter } from '../Utils';
+import { Utils, emptyPath, returnFalse, emptyFunction, returnOne, returnZero, returnTrue, returnEmptyFilter, returnEmptyDoclist } from '../Utils';
 import { Doc, Opt } from '../fields/Doc';
 import { Cast, FieldValue } from '../fields/Types';
 import { listSpec } from '../fields/Schema';
@@ -88,6 +88,7 @@ export class AudioUpload extends React.Component {
                         rootSelected={returnTrue}
                         removeDocument={undefined}
                         docFilters={returnEmptyFilter}
+                        searchFilterDocs={returnEmptyDoclist}
                         onClick={undefined}
                         ScreenToLocalTransform={Transform.Identity}
                         ContentScaling={returnOne}
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index 41b997285..05a695147 100644
--- a/src/mobile/MobileInterface.tsx
+++ b/src/mobile/MobileInterface.tsx
@@ -14,7 +14,7 @@ import { action, computed, observable, reaction, trace, runInAction } from 'mobx
 import { observer } from 'mobx-react';
 import { Doc, DocListCast } from '../fields/Doc';
 import { CurrentUserUtils } from '../client/util/CurrentUserUtils';
-import { emptyFunction, emptyPath, returnFalse, returnOne, returnTrue, returnZero, returnEmptyFilter } from '../Utils';
+import { emptyFunction, emptyPath, returnFalse, returnOne, returnTrue, returnZero, returnEmptyFilter, returnEmptyDoclist } from '../Utils';
 import { Docs, DocumentOptions } from '../client/documents/Documents';
 import { Scripting } from '../client/util/Scripting';
 import { DocumentView } from '../client/views/nodes/DocumentView';
@@ -220,6 +220,7 @@ export class MobileInterface extends React.Component {
                     whenActiveChanged={emptyFunction}
                     bringToFront={emptyFunction}
                     docFilters={returnEmptyFilter}
+                    searchFilterDocs={returnEmptyDoclist}
                     ContainingCollectionView={undefined}
                     ContainingCollectionDoc={undefined}
                 />
-- 
cgit v1.2.3-70-g09d2

