From 9d6c7f8100de3a952d20ad41ab20872737cb909e Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sun, 27 Aug 2023 20:25:55 -0400
Subject: lots of cleanup to streamline import orderings (ie packages should
 not mutually import each other directly or via a chain).  change
 raiseWhenDragged to be keepZWhenDragged and got rid of system wide default.

---
 src/client/views/collections/CollectionDockingView.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index e15d57306..519b7c905 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -3,6 +3,7 @@ import { observer } from 'mobx-react';
 import * as ReactDOM from 'react-dom/client';
 import * as GoldenLayout from '../../../client/goldenLayout';
 import { Doc, DocListCast, Opt } from '../../../fields/Doc';
+import { AclAdmin, AclEdit } from '../../../fields/DocSymbols';
 import { Id } from '../../../fields/FieldSymbols';
 import { InkTool } from '../../../fields/InkField';
 import { List } from '../../../fields/List';
@@ -13,6 +14,7 @@ import { emptyFunction, incrementTitleCopy } from '../../../Utils';
 import { DocServer } from '../../DocServer';
 import { Docs } from '../../documents/Documents';
 import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
+import { DocumentManager } from '../../util/DocumentManager';
 import { DragManager } from '../../util/DragManager';
 import { InteractionUtils } from '../../util/InteractionUtils';
 import { ScriptingGlobals } from '../../util/ScriptingGlobals';
@@ -28,8 +30,6 @@ import './CollectionDockingView.scss';
 import { CollectionFreeFormView } from './collectionFreeForm';
 import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
 import { TabDocView } from './TabDocView';
-import { DocumentManager } from '../../util/DocumentManager';
-import { AclAdmin, AclEdit } from '../../../fields/DocSymbols';
 import React = require('react');
 const _global = (window /* browser */ || global) /* node */ as any;
 
-- 
cgit v1.2.3-70-g09d2


From cfc406e52b5ddedc836d1b5342dbe5f6692917cd Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 13 Sep 2023 15:52:59 -0400
Subject: fixed undoing tab-> freeform dragging.

---
 src/client/views/collections/CollectionDockingView.tsx | 1 +
 1 file changed, 1 insertion(+)

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

diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 519b7c905..8472c59db 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -118,6 +118,7 @@ export class CollectionDockingView extends CollectionSubView() {
                 const j = tab.header.parent.contentItems.indexOf(tab.contentItem);
                 if (j !== -1) {
                     tab.header.parent.contentItems[j].remove();
+                    CollectionDockingView.Instance.endUndoBatch();
                     return CollectionDockingView.Instance.layoutChanged();
                 }
             }
-- 
cgit v1.2.3-70-g09d2


From 9bff82f5d53f7d13802f8affc4759db0953d7dc7 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 19 Sep 2023 14:15:52 -0400
Subject: made goldenlayout tabs/buttons follow color scheme + added hover
 highlights. got rid of old color scheme code.

---
 src/client/goldenLayout.js                         |  14 +-
 src/client/util/CurrentUserUtils.ts                |  14 +-
 src/client/views/DocumentDecorations.tsx           |  10 +-
 src/client/views/MainView.scss                     |  90 +----
 src/client/views/MainView.tsx                      |   9 +-
 src/client/views/StyleProvider.tsx                 |  26 +-
 .../views/collections/CollectionDockingView.scss   | 396 +++++++++++++++++++--
 .../views/collections/CollectionDockingView.tsx    |  57 +--
 src/client/views/collections/TabDocView.tsx        |   1 +
 .../CollectionFreeFormLayoutEngines.tsx            |   2 +-
 .../views/nodes/formattedText/DashDocView.tsx      |   2 +-
 src/mobile/MobileInterface.tsx                     |   5 +-
 12 files changed, 448 insertions(+), 178 deletions(-)

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

diff --git a/src/client/goldenLayout.js b/src/client/goldenLayout.js
index 843b8bb5f..00ec5e439 100644
--- a/src/client/goldenLayout.js
+++ b/src/client/goldenLayout.js
@@ -1606,10 +1606,10 @@
             dragProxyHeight: 200
         },
         labels: {
-            close: 'close',
-            maximise: 'maximise',
+            close: 'close tab stack',
+            maximise: 'maximize stack',
             minimise: 'minimise',
-            popout: 'new tab',
+            popout: 'create new collection tab',
             popin: 'pop in',
             tabDropdown: 'additional tabs'
         }
@@ -2922,7 +2922,7 @@
      * @type {String}
      */
     lm.controls.Tab._template = '<li class="lm_tab"><i class="lm_left"></i>' +
-        '<div class="lm_title_wrap"><input class="lm_title"/></div><div class="lm_close_tab"></div>' +
+        '<div class="lm_title_wrap"><input class="lm_title"/></div><div class="lm_close_tab" title="close tab"></div>' +
         '<i class="lm_right"></i></li>';
 
     lm.utils.copy(lm.controls.Tab.prototype, {
@@ -5083,10 +5083,10 @@
             'column',
             'stack',
             'component',
-            'close',
-            'maximise',
+            'close tab stack',
+            'maximize stack',
             'minimise',
-            'new tab'
+            'create new collection tab'
         ];
     };
 
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 452bb74cd..2983d778f 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -476,7 +476,6 @@ export class CurrentUserUtils {
     static setupDashboards(doc: Doc, field:string) {
         var myDashboards = DocCast(doc[field]);
 
-        const toggleDarkTheme = `this.colorScheme = this.colorScheme ? undefined : "${ColorScheme.Dark}"`;
         const newDashboard = `createNewDashboard()`;
 
         const reqdBtnOpts:DocumentOptions = { _forceActive: true,  _width: 30, _height: 30, _dragOnlyWithinContainer: true, _layout_hideContextMenu: true,
@@ -487,10 +486,10 @@ export class CurrentUserUtils {
         const contextMenuScripts = [/*newDashboard*/] as string[];
         const contextMenuLabels = [/*"Create New Dashboard"*/]  as string[];
         const contextMenuIcons = [/*"plus"*/]  as string[];
-        const childContextMenuScripts = [toggleDarkTheme, `toggleComicMode()`, `snapshotDashboard()`, `shareDashboard(self)`, 'removeDashboard(self)', 'resetDashboard(self)']; // entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuFilters
-        const childContextMenuFilters =  ['!IsNoviceMode()', '!IsNoviceMode()', '!IsNoviceMode()', undefined as any, undefined as any, '!IsNoviceMode()'];// entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuScripts
-        const childContextMenuLabels =  ["Toggle Dark Theme", "Toggle Comic Mode", "Snapshot Dashboard", "Share Dashboard", "Remove Dashboard", "Reset Dashboard"];// entries must be kept in synch with childContextMenuScripts, childContextMenuIcons, and childContextMenuFilters
-        const childContextMenuIcons = ["chalkboard", "tv", "camera", "users", "times", "trash"]; // entries must be kept in synch with childContextMenuScripts, childContextMenuLabels, and childContextMenuFilters
+        const childContextMenuScripts = [`toggleComicMode()`, `snapshotDashboard()`, `shareDashboard(self)`, 'removeDashboard(self)', 'resetDashboard(self)']; // entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuFilters
+        const childContextMenuFilters =  ['!IsNoviceMode()', '!IsNoviceMode()', undefined as any, undefined as any, '!IsNoviceMode()'];// entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuScripts
+        const childContextMenuLabels =  ["Toggle Comic Mode", "Snapshot Dashboard", "Share Dashboard", "Remove Dashboard", "Reset Dashboard"];// entries must be kept in synch with childContextMenuScripts, childContextMenuIcons, and childContextMenuFilters
+        const childContextMenuIcons = ["tv", "camera", "users", "times", "trash"]; // entries must be kept in synch with childContextMenuScripts, childContextMenuLabels, and childContextMenuFilters
         const reqdOpts:DocumentOptions = {
             title: "My Dashboards", childHideLinkButton: true, treeView_FreezeChildren: "remove|add", treeView_HideTitle: true, layout_boxShadow: "0 0", childDontRegisterViews: true,
             dropAction: "same", treeView_Type: TreeViewType.fileSystem, isFolder: true, isSystem: true,  treeView_TruncateTitleWidth: 350, ignoreClick: true, 
@@ -892,7 +891,6 @@ export class CurrentUserUtils {
         doc.defaultAclPrivate ?? (doc.defaultAclPrivate = false);
         doc.savedFilters ?? (doc.savedFilters = new List<Doc>());
         doc.userBackgroundColor ?? (doc.userBackgroundColor = Colors.DARK_GRAY);
-        addStyleSheetRule(SettingsManager._settingsStyle, 'lm_header', { background: `${doc.userBackgroundColor} !important` });
         doc.userVariantColor ?? (doc.userVariantColor = Colors.MEDIUM_BLUE);
         doc.userColor ?? (doc.userColor = Colors.LIGHT_GRAY);
         doc.userTheme ?? (doc.userTheme = ColorScheme.Dark);
@@ -920,10 +918,6 @@ export class CurrentUserUtils {
 
         Doc.GetProto(DocCast(Doc.UserDoc().emptyWebpage)).data = new WebField("https://www.wikipedia.org")
 
-        if (doc.activeDashboard instanceof Doc) {
-            // undefined means ColorScheme.Light until all CSS is updated with values for each color scheme (e.g., see MainView.scss, DocumentDecorations.scss)
-            doc.activeDashboard.colorScheme = doc.activeDashboard.colorScheme === ColorScheme.Light ? undefined : doc.activeDashboard.colorScheme;
-        }
         new LinkManager();
 
         DocServer.CacheNeedsUpdate && setTimeout(DocServer.UPDATE_SERVER_CACHE, 2500);
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 7e55b0ebc..327bb5585 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -804,8 +804,6 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
             </Tooltip>
         );
 
-        const colorScheme = StrCast(Doc.ActiveDashboard?.colorScheme);
-
         const leftBounds = this.props.boundsLeft;
         const topBounds = LightboxView.LightboxDoc ? 0 : this.props.boundsTop;
         bounds.x = Math.max(leftBounds, bounds.x - this._resizeBorderWidth / 2) + this._resizeBorderWidth / 2;
@@ -818,7 +816,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
         const useRotation = !hideResizers && seldocview.rootDoc.type !== DocumentType.EQUATION && seldocview.props.CollectionFreeFormDocumentView; // when do we want an object to not rotate?
         const rotation = SelectionManager.Views().length == 1 ? NumCast(seldocview.rootDoc._rotation) : 0;
 
-        const resizerScheme = colorScheme ? 'documentDecorations-resizer' + colorScheme : '';
+        const resizerScheme = '';
 
         // Radius constants
         const useRounding = seldocview.ComponentView instanceof ImageBox || seldocview.ComponentView instanceof FormattedTextBox || seldocview.ComponentView instanceof CollectionFreeFormView;
@@ -853,7 +851,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
         const titleArea = this._editingTitle ? (
             <input
                 ref={this._keyinput}
-                className={`documentDecorations-title${colorScheme}`}
+                className="documentDecorations-title"
                 type="text"
                 name="dynbox"
                 autoComplete="on"
@@ -871,7 +869,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                     e.stopPropagation;
                 }}>
                 {hideTitle ? null : (
-                    <span className={`documentDecorations-titleSpan${colorScheme}`} onPointerDown={this.onTitleDown}>
+                    <span className="documentDecorations-titleSpan" onPointerDown={this.onTitleDown}>
                         {this.selectionTitle}
                     </span>
                 )}
@@ -887,7 +885,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
         );
 
         return (
-            <div className={`documentDecorations${colorScheme}`} style={{ display: this._showNothing ? 'none' : undefined }}>
+            <div className="documentDecorations" style={{ display: this._showNothing ? 'none' : undefined }}>
                 <div
                     className="documentDecorations-background"
                     style={{
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index c880dde9a..98367969b 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -62,8 +62,7 @@ h1,
     pointer-events: none;
 }
 
-.mainView-container,
-.mainView-container-Dark {
+.mainView-container {
     width: 100%;
     height: 100%;
     position: absolute;
@@ -74,58 +73,12 @@ h1,
     touch-action: none;
 }
 
-.mainView-container,
-.mainView-container-Dark {
-    .lm_header .lm_tab {
-        padding: 0px;
-        //opacity: 0.7;
-        box-shadow: none;
-        height: 25px;
-        border-bottom: black solid;
-    }
-}
-
 .mainView-container {
     color: $dark-gray;
 
     .lm_goldenlayout {
         background: $medium-gray;
     }
-
-    .lm_title {
-        background: $light-gray;
-        color: $dark-gray;
-    }
-}
-
-.mainView-container-Dark {
-    color: $light-gray;
-
-    .lm_goldenlayout {
-        background: $medium-gray;
-    }
-
-    .lm_title {
-        background: $dark-gray;
-        color: unset;
-    }
-
-    .marquee {
-        border-color: $white;
-    }
-
-    #search-input {
-        background: $light-gray;
-    }
-
-    .contextMenu-cont,
-    .contextMenu-item {
-        background: $dark-gray;
-    }
-
-    .contextMenu-item:hover {
-        background: $medium-gray;
-    }
 }
 
 .mainView-dashboardArea {
@@ -172,8 +125,7 @@ h1,
     }
 }
 
-.mainView-innerContent,
-.mainView-innerContent-Dark {
+.mainView-innerContent {
     display: contents;
     flex-direction: row;
     position: relative;
@@ -206,44 +158,6 @@ h1,
     background-color: $light-gray;
 }
 
-.mainView-innerContent-Dark {
-    .propertiesView {
-        background-color: #252525;
-
-        input {
-            background-color: $medium-gray;
-        }
-
-        .propertiesView-sharingTable {
-            background-color: $medium-gray;
-        }
-
-        .editable-title {
-            background-color: $medium-gray;
-        }
-
-        .propertiesView-field {
-            background-color: $medium-gray;
-        }
-    }
-
-    .mainView-propertiesDragger,
-    .mainView-libraryHandle {
-        background: #353535;
-    }
-}
-
-.mainView-container-Dark {
-    .contextMenu-cont {
-        background: $medium-gray;
-        color: $white;
-
-        input::placeholder {
-            color: $white;
-        }
-    }
-}
-
 .mainView-leftMenuPanel {
     min-width: var(--menuPanelWidth);
     border-right: $standard-border;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 707cf3a34..6d08c01fa 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -112,9 +112,6 @@ export class MainView extends React.Component {
     @computed private get userDoc() {
         return Doc.UserDoc();
     }
-    @computed private get colorScheme() {
-        return StrCast(Doc.ActiveDashboard?.colorScheme);
-    }
     @observable mainDoc: Opt<Doc>;
     @computed private get mainContainer() {
         if (window.location.pathname.startsWith('/doc/') && Doc.CurrentUserEmail === 'guest') {
@@ -800,7 +797,7 @@ export class MainView extends React.Component {
         return (
             <>
                 {this._hideUI ? null : this.leftMenuPanel}
-                <div key="inner" className={`mainView-innerContent${this.colorScheme}`}>
+                <div key="inner" className="mainView-innerContent">
                     {this.flyout}
                     <div
                         className="mainView-libraryHandle"
@@ -843,7 +840,7 @@ export class MainView extends React.Component {
                         ).observe(r);
                 }}
                 style={{
-                    color: this.colorScheme === ColorScheme.Dark ? 'rgb(205,205,205)' : 'black',
+                    color: 'black',
                     height: `calc(100% - ${this.topOfDashUI + this.topMenuHeight()}px)`,
                     width: '100%',
                 }}>
@@ -1003,7 +1000,7 @@ export class MainView extends React.Component {
     render() {
         return (
             <div
-                className={`mainView-container ${this.colorScheme}`}
+                className="mainView-container"
                 style={{
                     color: SettingsManager.userColor,
                     background: SettingsManager.userBackgroundColor,
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 1a4b8d7d2..d7537bffb 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -52,10 +52,6 @@ export enum StyleProp {
     Highlighting = 'highlighting', // border highlighting
 }
 
-function darkScheme() {
-    return Doc.ActiveDashboard?.colorScheme === ColorScheme.Dark;
-}
-
 function toggleLockedPosition(doc: Doc) {
     UndoManager.RunInBatch(
         () =>
@@ -135,7 +131,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             }
             return undefined;
         case StyleProp.DocContents:return undefined;
-        case StyleProp.WidgetColor:return isAnnotated ? Colors.LIGHT_BLUE : darkScheme() ? 'lightgrey' : 'dimgrey';
+        case StyleProp.WidgetColor:return isAnnotated ? Colors.LIGHT_BLUE : 'dimgrey';
         case StyleProp.Opacity:    return props?.LayoutTemplateString?.includes(KeyValueBox.name) ? 1 : doc?.text_inlineAnnotations ? 0 :  Cast(doc?._opacity, "number", Cast(doc?.opacity, 'number', null));
         case StyleProp.HideLinkBtn:return props?.hideLinkButton || (!selected && doc?.layout_hideLinkButton);
         case StyleProp.FontSize:   return StrCast(doc?.[fieldKey + 'fontSize'],   StrCast(doc?._text_fontSize,   StrCast(Doc.UserDoc().fontSize)));
@@ -203,21 +199,21 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             // prettier-ignore
             switch (doc?.type) {
                 case DocumentType.SLIDER:      break;
-                case DocumentType.PRESELEMENT: docColor = docColor || (darkScheme() ? '' : ''); break;
-                case DocumentType.PRES:        docColor = docColor || (darkScheme() ? 'transparent' : 'transparent'); break;
+                case DocumentType.PRESELEMENT: docColor = docColor || ""; break;
+                case DocumentType.PRES:        docColor = docColor || 'transparent'; break;
                 case DocumentType.FONTICON:    docColor = boxBackground ? undefined : docColor || Colors.DARK_GRAY; break;
-                case DocumentType.RTF:         docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break;
+                case DocumentType.RTF:         docColor = docColor ||  Colors.LIGHT_GRAY; break;
                 case DocumentType.INK:         docColor = doc?.stroke_isInkMask ? 'rgba(0,0,0,0.7)' : undefined; break;
                 case DocumentType.EQUATION:    docColor = docColor || 'transparent'; break;
-                case DocumentType.LABEL:       docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break;
-                case DocumentType.BUTTON:      docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break;
+                case DocumentType.LABEL:       docColor = docColor || Colors.LIGHT_GRAY; break;
+                case DocumentType.BUTTON:      docColor = docColor ||  Colors.LIGHT_GRAY; break;
                 case DocumentType.LINK:        docColor = (isAnchor ? docColor : '') || 'transparent'; break;
                 case DocumentType.IMG:
                 case DocumentType.WEB:
                 case DocumentType.PDF:
                 case DocumentType.MAP:
                 case DocumentType.SCREENSHOT:
-                case DocumentType.VID:         docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break;
+                case DocumentType.VID:         docColor = docColor || (Colors.LIGHT_GRAY); break;
                 case DocumentType.COL:
                     if (StrCast(Doc.LayoutField(doc)).includes(SliderBox.name)) break;
                     docColor = docColor || (Doc.IsSystem(doc)
@@ -227,11 +223,11 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                             : doc?._isGroup
                             ? undefined
                             : doc._type_collection === CollectionViewType.Stacking ?
-                            (darkScheme() ? Colors.MEDIUM_GRAY : Colors.DARK_GRAY)
-                            : Cast((props?.renderDepth || 0) > 0 ? Doc.UserDoc().activeCollectionNestedBackground : Doc.UserDoc().activeCollectionBackground, 'string') ?? (darkScheme() ? Colors.BLACK : Colors.MEDIUM_GRAY));
+                            (Colors.DARK_GRAY)
+                            : Cast((props?.renderDepth || 0) > 0 ? Doc.UserDoc().activeCollectionNestedBackground : Doc.UserDoc().activeCollectionBackground, 'string') ?? (Colors.MEDIUM_GRAY));
                     break;
                 //if (doc._type_collection !== CollectionViewType.Freeform && doc._type_collection !== CollectionViewType.Time) return "rgb(62,62,62)";
-                default: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.WHITE);
+                default: docColor = docColor || (Colors.WHITE);
             }
             return (docColor && !doc) ? DashColor(docColor).fade(0.5).toString() : docColor;
         }
@@ -247,7 +243,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                             ? '4px 4px 10px 2px'
                             : lockedPosition() || doc?._isGroup || docProps?.LayoutTemplateString
                             ? undefined // groups have no drop shadow -- they're supposed to be "invisible".  LayoutString's imply collection is being rendered as something else (e.g., title of a Slide)
-                            : `${darkScheme() ? Colors.DARK_GRAY : Colors.MEDIUM_GRAY} ${StrCast(doc.layout_boxShadow, '0.2vw 0.2vw 0.8vw')}`
+                            : `${Colors.MEDIUM_GRAY} ${StrCast(doc.layout_boxShadow, '0.2vw 0.2vw 0.8vw')}`
                     );
 
                 case DocumentType.LABEL:
diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss
index b13753025..132250bae 100644
--- a/src/client/views/collections/CollectionDockingView.scss
+++ b/src/client/views/collections/CollectionDockingView.scss
@@ -1,5 +1,284 @@
 @import '../global/globalCssVariables.scss';
-@import '../../../../node_modules/golden-layout/src/css/goldenlayout-base.css';
+
+.lm_root {
+    position: relative;
+}
+.lm_row > .lm_item {
+    float: left;
+}
+.lm_content {
+    overflow: hidden;
+    position: relative;
+}
+.lm_dragging,
+.lm_dragging * {
+    cursor: move !important;
+    user-select: none;
+}
+.lm_maximised {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 40;
+}
+.lm_maximise_placeholder {
+    display: none;
+}
+.lm_splitter {
+    position: relative;
+    z-index: 20;
+}
+.lm_splitter:hover,
+.lm_splitter.lm_dragging {
+    background: orange;
+}
+.lm_splitter.lm_vertical .lm_drag_handle {
+    width: 100%;
+    position: absolute;
+    cursor: ns-resize;
+}
+.lm_splitter.lm_horizontal {
+    float: left;
+    height: 100%;
+}
+.lm_splitter.lm_horizontal .lm_drag_handle {
+    height: 100%;
+    position: absolute;
+    cursor: ew-resize;
+}
+.lm_header {
+    overflow: visible;
+    position: relative;
+    z-index: 1;
+}
+// .lm_header [class^='lm_'] {
+//     box-sizing: content-box !important;
+// }
+.lm_header .lm_controls {
+    position: absolute;
+    right: 3px;
+}
+.lm_header .lm_controls > li {
+    cursor: pointer;
+    float: left;
+    width: 18px;
+    height: 18px;
+    text-align: center;
+}
+.lm_header ul {
+    margin: 0;
+    padding: 0;
+    list-style-type: none;
+}
+.lm_header .lm_tabs {
+    position: absolute;
+}
+.lm_header .lm_tab {
+    cursor: pointer;
+    float: left;
+    height: 25px;
+    padding: 0 10px 5px;
+    padding-right: 25px;
+    position: relative;
+    box-shadow: unset !important;
+}
+.lm_header .lm_tab i {
+    width: 2px;
+    height: 19px;
+    position: absolute;
+}
+.lm_header .lm_tab i.lm_left {
+    top: 0;
+    left: -2px;
+}
+.lm_header .lm_tab i.lm_right {
+    top: 0;
+    right: -2px;
+}
+.lm_header .lm_tab .lm_title {
+    display: inline-block;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+.lm_header .lm_tab .lm_close_tab {
+    width: 14px;
+    height: 14px;
+    position: absolute;
+    top: 0;
+    right: 0;
+    text-align: center;
+}
+.lm_stack.lm_left .lm_header,
+.lm_stack.lm_right .lm_header {
+    height: 100%;
+}
+.lm_dragProxy.lm_left .lm_header,
+.lm_dragProxy.lm_right .lm_header,
+.lm_stack.lm_left .lm_header,
+.lm_stack.lm_right .lm_header {
+    width: 20px;
+    float: left;
+    vertical-align: top;
+}
+.lm_dragProxy.lm_left .lm_header .lm_tabs,
+.lm_dragProxy.lm_right .lm_header .lm_tabs,
+.lm_stack.lm_left .lm_header .lm_tabs,
+.lm_stack.lm_right .lm_header .lm_tabs {
+    transform-origin: left top;
+    top: 0;
+    width: 1000px;
+}
+.lm_dragProxy.lm_left .lm_header .lm_controls,
+.lm_dragProxy.lm_right .lm_header .lm_controls,
+.lm_stack.lm_left .lm_header .lm_controls,
+.lm_stack.lm_right .lm_header .lm_controls {
+    bottom: 0;
+}
+.lm_dragProxy.lm_left .lm_items,
+.lm_dragProxy.lm_right .lm_items,
+.lm_stack.lm_left .lm_items,
+.lm_stack.lm_right .lm_items {
+    float: left;
+}
+.lm_dragProxy.lm_left .lm_header .lm_tabs,
+.lm_stack.lm_left .lm_header .lm_tabs {
+    transform: rotate(-90deg) scaleX(-1);
+    left: 0;
+}
+.lm_dragProxy.lm_left .lm_header .lm_tabs .lm_tab,
+.lm_stack.lm_left .lm_header .lm_tabs .lm_tab {
+    transform: scaleX(-1);
+    margin-top: 1px;
+}
+.lm_dragProxy.lm_left .lm_header .lm_tabdropdown_list,
+.lm_stack.lm_left .lm_header .lm_tabdropdown_list {
+    top: initial;
+    right: initial;
+    left: 20px;
+}
+.lm_dragProxy.lm_right .lm_content {
+    float: left;
+}
+.lm_dragProxy.lm_right .lm_header .lm_tabs,
+.lm_stack.lm_right .lm_header .lm_tabs {
+    transform: rotate(90deg) scaleX(1);
+    left: 100%;
+    margin-left: 0;
+}
+.lm_dragProxy.lm_right .lm_header .lm_controls,
+.lm_stack.lm_right .lm_header .lm_controls {
+    left: 3px;
+}
+.lm_dragProxy.lm_right .lm_header .lm_tabdropdown_list,
+.lm_stack.lm_right .lm_header .lm_tabdropdown_list {
+    top: initial;
+    right: 20px;
+}
+.lm_dragProxy.lm_bottom .lm_header .lm_tab,
+.lm_stack.lm_bottom .lm_header .lm_tab {
+    margin-top: 0;
+    border-top: none;
+}
+.lm_dragProxy.lm_bottom .lm_header .lm_controls,
+.lm_stack.lm_bottom .lm_header .lm_controls {
+    top: 3px;
+}
+.lm_dragProxy.lm_bottom .lm_header .lm_tabdropdown_list,
+.lm_stack.lm_bottom .lm_header .lm_tabdropdown_list {
+    top: initial;
+    bottom: 20px;
+}
+.lm_drop_tab_placeholder {
+    float: left;
+    width: 100px;
+    height: 10px;
+    visibility: hidden;
+}
+.lm_header .lm_controls .lm_tabdropdown:before {
+    content: '';
+    width: 0;
+    height: 0;
+    vertical-align: middle;
+    display: inline-block;
+    border-top: 5px dashed;
+    border-right: 5px solid transparent;
+    border-left: 5px solid transparent;
+    color: white;
+}
+.lm_header .lm_tabdropdown_list {
+    position: absolute;
+    top: 20px;
+    right: 0;
+    z-index: 5;
+    overflow: hidden;
+}
+.lm_header .lm_tabdropdown_list .lm_tab {
+    clear: both;
+    padding-right: 10px;
+    margin: 0;
+}
+.lm_header .lm_tabdropdown_list .lm_tab .lm_title {
+    width: 100px;
+}
+.lm_header .lm_tabdropdown_list .lm_close_tab {
+    display: none !important;
+}
+.lm_dragProxy {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 30;
+}
+.lm_dragProxy .lm_header {
+    background: transparent;
+}
+.lm_dragProxy .lm_content {
+    border-top: none;
+    overflow: hidden;
+}
+.lm_dropTargetIndicator {
+    display: none;
+    position: absolute;
+    z-index: 20;
+}
+.lm_dropTargetIndicator .lm_inner {
+    width: 100%;
+    height: 100%;
+    position: relative;
+    top: 0;
+    left: 0;
+}
+.lm_transition_indicator {
+    display: none;
+    width: 20px;
+    height: 20px;
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 20;
+}
+.lm_popin {
+    width: 20px;
+    height: 20px;
+    position: absolute;
+    bottom: 0;
+    right: 0;
+    z-index: 9999;
+}
+.lm_popin > * {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    top: 0;
+    left: 0;
+}
+.lm_popin > .lm_bg {
+    z-index: 10;
+}
+.lm_popin > .lm_icon {
+    z-index: 20;
+} /*# sourceMappingURL=goldenlayout-base.css.map */
+
 @import '../../../../node_modules/golden-layout/src/css/goldenlayout-dark-theme.css';
 
 .lm_title {
@@ -46,18 +325,33 @@
     // font-weight: 700;
 }
 
+.lm_header .lm_tabs {
+    overflow-y: hidden;
+    width: 100%;
+}
+ul.lm_tabs::before {
+    content: ' ';
+    position: absolute;
+    bottom: 0;
+    width: 100%;
+    z-index: 1;
+    pointer-events: none;
+    border: solid 1px black;
+}
 .lm_header .lm_tab {
     // padding: 0px;  // moved to MainView.scss, othwerise they get overridden by default stylings
     // opacity: 0.7;
     // box-shadow: none;
     // height: 25px;
     // border-bottom: black solid;
+    border-bottom: unset !important;
+    border-top-right-radius: 5px;
+    border-top-left-radius: 5px;
 
     .collectionDockingView-gear {
         display: none;
     }
 }
-
 .lm_header .lm_tab.lm_active {
     padding: 0;
     opacity: 1;
@@ -65,7 +359,11 @@
     box-shadow: none;
     height: 27px;
     margin-right: 2px;
-    // border-bottom: unset;
+    z-index: 2 !important;
+    border-right: solid 2px;
+    border-left: solid 2px;
+    border-top: solid 2px;
+    border-color: black;
 
     .collectionDockingView-gear {
         display: inline-block;
@@ -123,20 +421,63 @@
 }
 
 .lm_close_tab {
+    display: inline-flex !important;
+    opacity: 0 !important;
     padding: 0;
     align-self: center;
     margin-right: 5px;
-    background-color: black;
     border-radius: 3px;
-    opacity: 1 !important;
     width: 15px !important;
     height: 15px !important;
     position: relative !important;
-    display: inline-flex !important;
     align-items: center;
     top: 0 !important;
     right: unset !important;
     left: 0 !important;
+    background-image: unset !important;
+    &::before {
+        content: 'x';
+        color: rgb(50, 50, 50);
+        margin: auto;
+        position: relative;
+        top: -2px;
+    }
+    &:hover {
+        display: inline-flex !important;
+        &::before {
+            color: white;
+        }
+    }
+}
+.lm_close {
+    background-image: unset !important;
+    &:hover {
+        background: gray;
+        color: white !important;
+    }
+    &::before {
+        content: 'x';
+        margin: auto;
+        position: relative;
+        top: -2;
+        font-size: medium;
+        font-family: sans-serif;
+    }
+}
+.lm_active .lm_close_tab {
+    opacity: 1 !important;
+}
+.lm_tab:hover {
+    .lm_close_tab {
+        opacity: 1 !important;
+    }
+}
+
+.lm_iconWrap {
+    &:hover {
+        background: gray;
+        color: white !important;
+    }
 }
 
 .lm_tab,
@@ -154,14 +495,6 @@
     top: 0;
     left: 0;
 
-    // overflow: hidden;  // bcz: menus don't show up when this is on (e.g., the parentSelectorMenu)
-    .collectionDockingView-gear {
-        padding-left: 5px;
-        height: 15px;
-        width: 18px;
-        margin: auto;
-    }
-
     .collectionDockingView-drag {
         touch-action: none;
         position: absolute;
@@ -180,7 +513,6 @@
         display: flex;
         align-content: center;
         justify-content: center;
-        background: $dark-gray;
     }
 
     .lm_controls > li {
@@ -190,14 +522,38 @@
     }
 
     .lm_controls .lm_popout {
-        transform: rotate(45deg);
-        background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAQUlEQVR4nHXOQQ4AMAgCQeT/f6aXpsGK3jSTuCVJAAr7iBdoAwCKd0nwfaAdHbYERw5b44+E8JoBjEYGMBq5gAYP3usUDu2IvoUAAAAASUVORK5CYII=);
+        background-image: unset;
+        left: -3;
+        &:hover {
+            background: gray;
+            color: white !important;
+        }
+    }
+    li.lm_popout::before {
+        content: '+';
+        margin: auto;
+        font-size: x-large;
+        top: -8;
+        position: relative;
+    }
+    .lm_maximise {
+        background-image: unset !important;
+        &::before {
+            content: '\25A3';
+            margin: auto;
+            font-size: medium;
+            position: relative;
+        }
+        &:hover {
+            background: gray;
+            color: white !important;
+        }
     }
 
     .lm_maximised .lm_controls .lm_maximise {
-        opacity: 1;
-        transform: scale(0.8);
-        background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAKElEQVR4nGP8////fwYCgImQAgYGBgYWKM2IR81/okwajIpgvsMbVgAwgQYRVakEKQAAAABJRU5ErkJggg==) !important;
+        &::before {
+            content: '\25A2';
+        }
     }
 
     .flexlayout__layout {
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 8472c59db..4873a61ff 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -10,7 +10,7 @@ import { List } from '../../../fields/List';
 import { ImageCast, NumCast, StrCast } from '../../../fields/Types';
 import { ImageField } from '../../../fields/URLField';
 import { GetEffectiveAcl, inheritParentAcls } from '../../../fields/util';
-import { emptyFunction, incrementTitleCopy } from '../../../Utils';
+import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, incrementTitleCopy } from '../../../Utils';
 import { DocServer } from '../../DocServer';
 import { Docs } from '../../documents/Documents';
 import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
@@ -31,6 +31,7 @@ import { CollectionFreeFormView } from './collectionFreeForm';
 import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
 import { TabDocView } from './TabDocView';
 import React = require('react');
+import { SettingsManager } from '../../util/SettingsManager';
 const _global = (window /* browser */ || global) /* node */ as any;
 
 @observer
@@ -60,7 +61,7 @@ export class CollectionDockingView extends CollectionSubView() {
         return this._goldenLayout._maximisedItem !== null;
     }
     private _goldenLayout: any = null;
-
+    static _highlightStyleSheet: any = addStyleSheet();
     constructor(props: SubCollectionViewProps) {
         super(props);
         if (this.props.renderDepth < 0) runInAction(() => (CollectionDockingView.Instance = this));
@@ -330,6 +331,16 @@ export class CollectionDockingView extends CollectionSubView() {
                 width => !this._goldenLayout && width > 20 && setTimeout(() => this.setupGoldenLayout()), // need to wait for the collectiondockingview-container to have it's width/height since golden layout reads that to configure its windows
                 { fireImmediately: true }
             );
+            reaction(
+                () => [SettingsManager.userBackgroundColor, SettingsManager.userBackgroundColor],
+                () => {
+                    clearStyleSheetRules(CollectionDockingView._highlightStyleSheet);
+                    addStyleSheetRule(CollectionDockingView._highlightStyleSheet, 'lm_controls', { background: `${SettingsManager.userBackgroundColor} !important` });
+                    addStyleSheetRule(CollectionDockingView._highlightStyleSheet, 'lm_controls', { color: `${SettingsManager.userColor} !important` });
+                    addStyleSheetRule(SettingsManager._settingsStyle, 'lm_header', { background: `${SettingsManager.userBackgroundColor} !important` });
+                },
+                { fireImmediately: true }
+            );
         }
     };
 
@@ -505,6 +516,23 @@ export class CollectionDockingView extends CollectionSubView() {
             }
         });
 
+        let addNewDoc = action(() => {
+            const dashboard = Doc.ActiveDashboard;
+            if (dashboard) {
+                dashboard['pane-count'] = NumCast(dashboard['pane-count']) + 1;
+                const docToAdd = Docs.Create.FreeformDocument([], {
+                    _width: this.props.PanelWidth(),
+                    _height: this.props.PanelHeight(),
+                    _layout_fitWidth: true,
+                    _freeform_backgroundGrid: true,
+                    title: `Untitled Tab ${NumCast(dashboard['pane-count'])}`,
+                });
+                Doc.AddDocToList(Doc.MyHeaderBar, 'data', docToAdd);
+                inheritParentAcls(this.dataDoc, docToAdd, false);
+                CollectionDockingView.AddSplit(docToAdd, OpenWhereMod.none, stack);
+            }
+        });
+
         stack.header?.controlsContainer
             .find('.lm_close') //get the close icon
             .off('click') //unbind the current click handler
@@ -524,31 +552,18 @@ export class CollectionDockingView extends CollectionSubView() {
                 })
             );
 
+        stack.element.click((e: any) => {
+            if (stack.contentItems.length === 0 && Array.from(document.elementsFromPoint(e.originalEvent.x, e.originalEvent.y)).some(ele => ele?.className === 'empty-tabs-message')) {
+                addNewDoc();
+            }
+        });
         stack.header?.controlsContainer
             .find('.lm_maximise') //get the close icon
             .click(() => setTimeout(this.stateChanged));
         stack.header?.controlsContainer
             .find('.lm_popout') //get the popout icon
             .off('click') //unbind the current click handler
-            .click(
-                action(() => {
-                    // stack.config.fixed = !stack.config.fixed;  // force the stack to have a fixed size
-                    const dashboard = Doc.ActiveDashboard;
-                    if (dashboard) {
-                        dashboard['pane-count'] = NumCast(dashboard['pane-count']) + 1;
-                        const docToAdd = Docs.Create.FreeformDocument([], {
-                            _width: this.props.PanelWidth(),
-                            _height: this.props.PanelHeight(),
-                            _layout_fitWidth: true,
-                            _freeform_backgroundGrid: true,
-                            title: `Untitled Tab ${NumCast(dashboard['pane-count'])}`,
-                        });
-                        Doc.AddDocToList(Doc.MyHeaderBar, 'data', docToAdd);
-                        inheritParentAcls(this.dataDoc, docToAdd, false);
-                        CollectionDockingView.AddSplit(docToAdd, OpenWhereMod.none, stack);
-                    }
-                })
-            );
+            .click(addNewDoc);
     };
 
     render() {
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index dab53b671..26aa5a121 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -132,6 +132,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
 
             if (tab.element[0].children[1].children.length === 1) {
                 iconWrap.className = 'lm_iconWrap lm_moreInfo';
+                iconWrap.title = 'click for menu, drag to embed in document';
                 const dragBtnDown = (e: React.PointerEvent) => {
                     setupMoveUpEvents(
                         this,
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
index 1e76d373c..15b6e1d37 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
@@ -350,7 +350,7 @@ export function computeTimelineLayout(poolData: Map<string, PoolData>, pivotDoc:
         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: Doc.ActiveDashboard?.colorScheme === ColorScheme.Dark ? 'dimgray' : 'black', x: 0, y: 0, width: panelDim[0], height: -1, payload: undefined };
+    const divider = { type: 'div', color: '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/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx
index 48f4c2afd..5349e6966 100644
--- a/src/client/views/nodes/formattedText/DashDocView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocView.tsx
@@ -22,7 +22,7 @@ export class DashDocView {
         this.dom = document.createElement('span');
         this.dom.style.position = 'relative';
         this.dom.style.textIndent = '0';
-        this.dom.style.border = '1px solid ' + StrCast(tbox.layoutDoc.color, Doc.ActiveDashboard?.colorScheme === ColorScheme.Dark ? 'dimgray' : 'lightGray');
+        this.dom.style.border = '1px solid ' + StrCast(tbox.layoutDoc.color, 'lightGray');
         this.dom.style.width = node.attrs.width;
         this.dom.style.height = node.attrs.height;
         this.dom.style.display = node.attrs.hidden ? 'none' : 'inline-block';
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index c16a1c124..498bec6ed 100644
--- a/src/mobile/MobileInterface.tsx
+++ b/src/mobile/MobileInterface.tsx
@@ -588,11 +588,10 @@ export class MobileInterface extends React.Component {
         const freeformDoc = Doc.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions);
         const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: `Dashboard ${dashboardCount}` }, id, 'row');
 
-        const toggleTheme = ScriptField.MakeScript(`self.colorScheme = self.colorScheme ? undefined: ${ColorScheme.Dark}}`);
         const toggleComic = ScriptField.MakeScript(`toggleComicMode()`);
         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']);
+        dashboardDoc.contextMenuScripts = new List<ScriptField>([toggleComic!, cloneDashboard!]);
+        dashboardDoc.contextMenuLabels = new List<string>(['Toggle Comic Mode', 'New Dashboard Layout']);
 
         Doc.AddDocToList(scens, 'data', dashboardDoc);
     };
-- 
cgit v1.2.3-70-g09d2

