From 3c8cb517c811f94dce1e3d8430e07af316642365 Mon Sep 17 00:00:00 2001
From: sotech117 <michael_foiani@brown.edu>
Date: Thu, 13 Apr 2023 05:39:21 -0400
Subject: Compile and make compatible all the scattered code I had for
 empowering trails for dash meeting. Still much to do with ui, but basic
 functionaltiy is there. Two key things, 1) navigation for branching trails,
 and 2) ability to runSubroutines on tested trails.

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

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

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 60459cf30..1fc5ee1d7 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -63,6 +63,7 @@ import { PreviewCursor } from './PreviewCursor';
 import { PropertiesView } from './PropertiesView';
 import { DashboardStyleProvider, DefaultStyleProvider } from './StyleProvider';
 import { TopBar } from './topbar/TopBar';
+import { BranchingTrailManager } from '../util/BranchingTrailManager';
 const _global = (window /* browser */ || global) /* node */ as any;
 
 @observer
-- 
cgit v1.2.3-70-g09d2


From 2bc89733ce522527c2f27203b537d99395c9479b Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 17 Apr 2023 15:39:41 -0400
Subject: minor cleanup

---
 src/client/util/BranchingTrailManager.tsx  | 11 +++++------
 src/client/util/DocumentManager.ts         |  1 -
 src/client/views/MainView.tsx              |  5 ++---
 src/client/views/collections/TreeView.scss |  3 +--
 4 files changed, 8 insertions(+), 12 deletions(-)

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

diff --git a/src/client/util/BranchingTrailManager.tsx b/src/client/util/BranchingTrailManager.tsx
index 5a9dd7743..44cec6922 100644
--- a/src/client/util/BranchingTrailManager.tsx
+++ b/src/client/util/BranchingTrailManager.tsx
@@ -1,12 +1,11 @@
-import * as React from 'react';
-import { action, observable, computed } from 'mobx';
+import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
+import * as React from 'react';
 import { Doc } from '../../fields/Doc';
-import { PresBox } from '../views/nodes/trails';
 import { Id } from '../../fields/FieldSymbols';
-import { DocumentManager } from './DocumentManager';
+import { PresBox } from '../views/nodes/trails';
 import { OverlayView } from '../views/OverlayView';
-import { compute } from 'googleapis/build/src/apis/compute';
+import { DocumentManager } from './DocumentManager';
 
 @observer
 export class BranchingTrailManager extends React.Component {
@@ -71,7 +70,7 @@ export class BranchingTrailManager extends React.Component {
         }
     };
 
-    clickHandler = (e: React.PointerEventHandler<HTMLButtonElement>, targetDocId: string, removeIndex: number) => {
+    clickHandler = (e: React.PointerEvent<HTMLButtonElement>, targetDocId: string, removeIndex: number) => {
         const targetDoc = this.docIdToDocMap.get(targetDocId);
         if (!targetDoc) {
             return;
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 8263e1ba7..e01457b4f 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -15,7 +15,6 @@ import { LinkAnchorBox } from '../views/nodes/LinkAnchorBox';
 import { PresBox } from '../views/nodes/trails';
 import { ScriptingGlobals } from './ScriptingGlobals';
 import { SelectionManager } from './SelectionManager';
-import { BranchingTrailManager } from './BranchingTrailManager';
 const { Howl } = require('howler');
 
 export class DocumentManager {
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index f0f744886..f625d44fe 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -14,7 +14,7 @@ import { StrCast } from '../../fields/Types';
 import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents, Utils } from '../../Utils';
 import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager';
 import { DocServer } from '../DocServer';
-import { Docs, DocUtils } from '../documents/Documents';
+import { Docs } from '../documents/Documents';
 import { CollectionViewType, DocumentType } from '../documents/DocumentTypes';
 import { CaptureManager } from '../util/CaptureManager';
 import { DocumentManager } from '../util/DocumentManager';
@@ -40,7 +40,7 @@ import { DashboardView } from './DashboardView';
 import { DictationOverlay } from './DictationOverlay';
 import { DocumentDecorations } from './DocumentDecorations';
 import { GestureOverlay } from './GestureOverlay';
-import { TOPBAR_HEIGHT, LEFT_MENU_WIDTH } from './global/globalCssVariables.scss';
+import { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } from './global/globalCssVariables.scss';
 import { Colors } from './global/globalEnums';
 import { KeyManager } from './GlobalKeyHandler';
 import { InkTranscription } from './InkTranscription';
@@ -63,7 +63,6 @@ import { PreviewCursor } from './PreviewCursor';
 import { PropertiesView } from './PropertiesView';
 import { DashboardStyleProvider, DefaultStyleProvider } from './StyleProvider';
 import { TopBar } from './topbar/TopBar';
-import { BranchingTrailManager } from '../util/BranchingTrailManager';
 const _global = (window /* browser */ || global) /* node */ as any;
 
 @observer
diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss
index cb6432687..185bed74c 100644
--- a/src/client/views/collections/TreeView.scss
+++ b/src/client/views/collections/TreeView.scss
@@ -25,10 +25,9 @@
         width: 100%;
         height: 100%;
         position: absolute;
-        left: 10px;
 
         .treeView-expandIcon {
-            // display: none;
+            display: none;
             left: -8px;
             position: absolute;
         }
-- 
cgit v1.2.3-70-g09d2


From 0c4f57875c8aaf599ff111a8b8122895d2addab3 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 29 Aug 2023 16:33:37 -0400
Subject: more cleanup

---
 src/client/util/CurrentUserUtils.ts                |   4 +-
 src/client/util/DragManager.ts                     |   7 +-
 src/client/views/DocComponent.tsx                  |   2 +-
 src/client/views/MainView.tsx                      |   2 +-
 src/client/views/ScriptingRepl.tsx                 |  23 +++-
 src/client/views/nodes/DocumentIcon.tsx            |   2 +
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |   2 +-
 .../views/nodes/RecordingBox/RecordingBox.tsx      | 139 ++++++++++++---------
 8 files changed, 105 insertions(+), 76 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index b705bde7f..51ef51508 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -715,14 +715,14 @@ export class CurrentUserUtils {
             { title: "View",    icon: "View",          toolTip: "View tools",           subMenu: CurrentUserUtils.viewTools(),   expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Always available
             { title: "Web",     icon: "Web",           toolTip: "Web functions",        subMenu: CurrentUserUtils.webTools(),    expertMode: false, toolType:DocumentType.WEB,            funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Web is selected
             { title: "Schema",  icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions",subMenu: CurrentUserUtils.schemaTools(), expertMode: false, toolType:CollectionViewType.Schema,   funcs: {hidden: `!SelectionManager_selectedDocType(self.toolType, self.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(self.toolType, self.expertMode)`} }, // Only when Schema is selected
-            { title: "Video",   icon: 'video',    toolTip: "Dictate",              btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `getIsRecording()`},                               ignoreClick: true,             scripts: { onClick:  'return toggleRecording(_readOnly_)'}},
+            { title: "Video",   icon: 'video',         toolTip: "Dictate",              btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `getIsRecording()`},                               ignoreClick: true,             scripts: { onClick:  'return toggleRecording(_readOnly_)'}},
             { title: "StopRec", icon: "stop",          toolTip: "Stop",                 btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsRecording()`},                              ignoreClick: true,             scripts: { onClick: `return toggleRecording(_readOnly_)`}},
             { title: "Dropdown",                       toolTip: "Workspace Recordings", btnType: ButtonType.DropdownList,        expertMode: false,                                       funcs: {hidden: `renderDropdown()`, btnList: `getWorkspaceRecordings()`},                      ignoreClick: true,             scripts: { script: `toggleRecPlayback(value)`}},
             { title: "Play Rec",icon: "play",          toolTip: "Play recording",       btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsWorkspaceRecPlaying()`},                            ignoreClick: true,             scripts: { onClick: `return playWorkspaceRec(getCurrentRecording())`}},
             { title: "Pause Rec",icon: "pause",        toolTip: "Pause recording",      btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsWorkspaceRecPaused()`},                            ignoreClick: true,             scripts: { onClick: `return pauseWorkspaceRec(getCurrentRecording())`}},
             { title: "Stop Rec", icon: "stop",         toolTip: "Stop recording",       btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsRecPlayback()`},                            ignoreClick: true,             scripts: { onClick: `return closeWorkspaceRec(getCurrentRecording())`}},
             { title: "Add doc", icon: "down",          toolTip: "add to doc",           btnType: ButtonType.ToggleButton,        expertMode: false,                                       funcs: {hidden: `!getIsRecPlayback()`},                            ignoreClick: true,             scripts: { onClick: `addRectoWorkspace(getCurrentRecording())`}},
-            { title: "Delete Rec", icon: "trash",    toolTip: "delete selected recording", btnType: ButtonType.ToggleButton,   expertMode: false,                                       funcs: {hidden: `!getIsRecPlayback()`},                                                         ignoreClick: true,             scripts: { onClick: `removeWorkspaceRec(getCurrentRecording())`}}
+            { title: "Delete Rec", icon: "trash",      toolTip: "delete selected recording", btnType: ButtonType.ToggleButton,   expertMode: false,                                       funcs: {hidden: `!getIsRecPlayback()`},                                                         ignoreClick: true,             scripts: { onClick: `removeWorkspaceRec(getCurrentRecording())`}}
         ];
     }
 
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 5a11f2dca..065f17139 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -4,7 +4,7 @@ import { Doc, Field, Opt, StrListCast } from '../../fields/Doc';
 import { List } from '../../fields/List';
 import { PrefetchProxy } from '../../fields/Proxy';
 import { ScriptField } from '../../fields/ScriptField';
-import { BoolCast, Cast, ScriptCast, StrCast } from '../../fields/Types';
+import { BoolCast, Cast, DocCast, ScriptCast, StrCast } from '../../fields/Types';
 import { emptyFunction, Utils } from '../../Utils';
 import { Docs, DocUtils } from '../documents/Documents';
 import * as globalCssVariables from '../views/global/globalCssVariables.scss';
@@ -236,8 +236,7 @@ export namespace DragManager {
         return true;
     }
 
-    export function StartDropdownDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, recordingIndex: number, options?: DragOptions, dropEvent?: () => any,) {
-        
+    export function StartDropdownDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, recordingIndex: number, options?: DragOptions, dropEvent?: () => any) {
         const addAudioTag = (dropDoc: any) => {
             dropDoc && !dropDoc.author_date && (dropDoc.author_date = new DateField());
             dropDoc instanceof Doc && DocUtils.MakeLinkToActiveAudio(() => dropDoc);
@@ -245,7 +244,7 @@ export namespace DragManager {
         };
         const finishDrag = async (e: DragCompleteEvent) => {
             Doc.UserDoc().isAddRecToDocMode = false;
-            Doc.RemFromMyOverlay(Doc.UserDoc().currentRecording);
+            Doc.RemFromMyOverlay(DocCast(Doc.UserDoc().currentRecording));
             Doc.UserDoc().currentRecording = undefined;
             Doc.UserDoc().isRecPlayback = false;
             Doc.UserDoc().isWorkspaceRecPlaying = false;
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index e076e69ca..6a1efdf9c 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -201,7 +201,7 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>()
                     const annoDocs = targetDataDoc[annotationKey ?? this.annotationKey] as List<Doc>;
                     if (annoDocs instanceof List) annoDocs.push(...added.filter(add => !annoDocs.includes(add)));
                     else targetDataDoc[annotationKey ?? this.annotationKey] = new List<Doc>(added);
-                    targetDataDoc[(annotationKey ?? this.annotationKey) + '_modificationDate'] = new DateField(new Date(Date.now()));
+                    targetDataDoc[(annotationKey ?? this.annotationKey) + '_modificationDate'] = new DateField();
                 }
             }
             return true;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index dde04dcc0..01a26559c 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -902,7 +902,7 @@ export class MainView extends React.Component {
                     childFiltersByRanges={returnEmptyFilter}
                     searchFilterDocs={returnEmptyDoclist}
                 />
-                {['watching', 'recording'].includes(String(this.userDoc?.presentationMode) ?? '') ? <div style={{ border: '.5rem solid green', padding: '5px' }}>{StrCast(this.userDoc?.presentationMode)}</div> : <></>}
+                {['watching', 'recording'].includes(StrCast(this.userDoc?.presentationMode)) ? <div style={{ border: '.5rem solid green', padding: '5px' }}>{StrCast(this.userDoc?.presentationMode)}</div> : <></>}
             </div>
         );
     }
diff --git a/src/client/views/ScriptingRepl.tsx b/src/client/views/ScriptingRepl.tsx
index 2bc2d5e6b..9966dbced 100644
--- a/src/client/views/ScriptingRepl.tsx
+++ b/src/client/views/ScriptingRepl.tsx
@@ -5,6 +5,7 @@ import * as React from 'react';
 import { DocumentManager } from '../util/DocumentManager';
 import { CompileScript, Transformer, ts } from '../util/Scripting';
 import { ScriptingGlobals } from '../util/ScriptingGlobals';
+import { SettingsManager } from '../util/SettingsManager';
 import { undoable } from '../util/UndoManager';
 import { DocumentIconContainer } from './nodes/DocumentIcon';
 import { OverlayView } from './OverlayView';
@@ -245,17 +246,29 @@ export class ScriptingRepl extends React.Component {
     render() {
         return (
             <div className="scriptingRepl-outerContainer">
-                <div className="scriptingRepl-commandsContainer" ref={this.commandsRef}>
+                <div className="scriptingRepl-commandsContainer" style={{ background: SettingsManager.userBackgroundColor }} ref={this.commandsRef}>
                     {this.commands.map(({ command, result }, i) => {
                         return (
-                            <div className="scriptingRepl-resultContainer" key={i}>
-                                <div className="scriptingRepl-commandString">{command || <br />}</div>
-                                <div className="scriptingRepl-commandResult">{<ScriptingValueDisplay scrollToBottom={this.maybeScrollToBottom} value={result} />}</div>
+                            <div className="scriptingRepl-resultContainer" style={{ background: SettingsManager.userBackgroundColor }} key={i}>
+                                <div className="scriptingRepl-commandString" style={{ background: SettingsManager.userBackgroundColor }}>
+                                    {command || <br />}
+                                </div>
+                                <div className="scriptingRepl-commandResult" style={{ background: SettingsManager.userBackgroundColor }}>
+                                    {<ScriptingValueDisplay scrollToBottom={this.maybeScrollToBottom} value={result} />}
+                                </div>
                             </div>
                         );
                     })}
                 </div>
-                <input className="scriptingRepl-commandInput" onFocus={this.onFocus} onBlur={this.onBlur} value={this.commandString} onChange={this.onChange} onKeyDown={this.onKeyDown}></input>
+                <input
+                    className="scriptingRepl-commandInput"
+                    style={{ background: SettingsManager.userBackgroundColor }} //
+                    onFocus={this.onFocus}
+                    onBlur={this.onBlur}
+                    value={this.commandString}
+                    onChange={this.onChange}
+                    onKeyDown={this.onKeyDown}
+                />
             </div>
         );
     }
diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx
index 6e2ed72b8..bccbd66e8 100644
--- a/src/client/views/nodes/DocumentIcon.tsx
+++ b/src/client/views/nodes/DocumentIcon.tsx
@@ -9,6 +9,7 @@ import { action, observable } from 'mobx';
 import { Id } from '../../../fields/FieldSymbols';
 import { factory } from 'typescript';
 import { LightboxView } from '../LightboxView';
+import { SettingsManager } from '../../util/SettingsManager';
 
 @observer
 export class DocumentIcon extends React.Component<{ view: DocumentView; index: number }> {
@@ -29,6 +30,7 @@ export class DocumentIcon extends React.Component<{ view: DocumentView; index: n
                     pointerEvents: 'all',
                     opacity: this._hovered ? 0.3 : 1,
                     position: 'absolute',
+                    background: SettingsManager.userBackgroundColor,
                     transform: `translate(${(left + right) / 2}px, ${top}px)`,
                 }}>
                 <Tooltip title={<>{this.props.view.rootDoc.title}</>}>
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 1cf66fbdc..bb2069cc9 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -235,7 +235,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         const list: IListItemProps[] = this.buttonList
             .filter(value => !Doc.noviceMode || !noviceList.length || noviceList.includes(value))
             .map(value => ({
-                text: value === "string" ? value.charAt(0).toUpperCase() + value.slice(1) : StrCast(DocCast(value)?.title),
+                text: typeof value === 'string' ? value.charAt(0).toUpperCase() + value.slice(1) : StrCast(DocCast(value)?.title),
                 val: value,
                 style: getStyle(value),
                 onClick: undoable(() => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value }), value),
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 8a91b8102..9dd673591 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -1,32 +1,27 @@
-import { action, observable, runInAction } from 'mobx';
+import { action, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { VideoField } from '../../../../fields/URLField';
-import { Upload } from '../../../../server/SharedMediaTypes';
-import { ViewBoxBaseComponent } from '../../DocComponent';
-import { FieldView, FieldViewProps } from '../FieldView';
-import { VideoBox } from '../VideoBox';
-import { RecordingView } from './RecordingView';
-import { DocumentType } from '../../../documents/DocumentTypes';
-import { Presentation } from '../../../util/TrackMovements';
+import { formatTime } from '../../../../Utils';
 import { Doc, DocListCast } from '../../../../fields/Doc';
 import { Id } from '../../../../fields/FieldSymbols';
+import { listSpec } from '../../../../fields/Schema';
 import { BoolCast, Cast, DocCast } from '../../../../fields/Types';
-import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
-import { DocumentManager } from '../../../util/DocumentManager';
+import { VideoField } from '../../../../fields/URLField';
+import { Upload } from '../../../../server/SharedMediaTypes';
 import { Docs } from '../../../documents/Documents';
-import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView';
-import { CurrentUserUtils } from '../../../util/CurrentUserUtils';
-import { DocumentView } from '../DocumentView';
-import { SettingsManager } from '../../../util/SettingsManager';
-import { PropertiesView } from '../../PropertiesView';
-import { PropertiesSection } from '../../PropertiesSection';
-import { PropertiesDocContextSelector } from '../../PropertiesDocContextSelector';
-import { listSpec } from '../../../../fields/Schema';
+import { DocumentType } from '../../../documents/DocumentTypes';
+import { DocumentManager } from '../../../util/DocumentManager';
 import { DragManager } from '../../../util/DragManager';
+import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
 import { SelectionManager } from '../../../util/SelectionManager';
-import { AudioBox } from '../AudioBox';
-import { UndoManager, undoBatch } from '../../../util/UndoManager';
+import { Presentation } from '../../../util/TrackMovements';
+import { undoBatch } from '../../../util/UndoManager';
+import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView';
+import { ViewBoxBaseComponent } from '../../DocComponent';
+import { FieldView, FieldViewProps } from '../FieldView';
+import { VideoBox } from '../VideoBox';
+import { RecordingView } from './RecordingView';
+import { DateField } from '../../../../fields/DateField';
 
 @observer
 export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
@@ -69,8 +64,8 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
 
     /**
      * This method toggles whether or not we are currently using the RecordingBox to record with the topbar button
-     * @param _readOnly_ 
-     * @returns 
+     * @param _readOnly_
+     * @returns
      */
     @undoBatch
     @action
@@ -78,33 +73,33 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
         if (_readOnly_) return RecordingBox.screengrabber ? true : false;
         if (RecordingBox.screengrabber) {
             //if recordingbox is true; when we press the stop button. changed vals temporarily to see if changes happening
-            console.log('grabbing screen!')
+            console.log('grabbing screen!');
             RecordingBox.screengrabber.Pause?.();
             const remDoc = RecordingBox.screengrabber.rootDoc;
             setTimeout(() => {
                 RecordingBox.screengrabber?.Finish?.();
                 RecordingBox.screengrabber!.rootDoc.overlayX = 70; //was 100
                 RecordingBox.screengrabber!.rootDoc.overlayY = 590;
-                console.log(RecordingBox.screengrabber)
+                console.log(RecordingBox.screengrabber);
                 RecordingBox.screengrabber = undefined;
             }, 100);
             //could break if recording takes too long to turn into videobox. If so, either increase time on setTimeout below or find diff place to do this
             setTimeout(() => {
                 Doc.RemFromMyOverlay(remDoc);
-    
-            }, 1000)
+            }, 1000);
             Doc.UserDoc().isRecording = false;
-            Doc.AddDocToList(Doc.UserDoc(), "workspaceRecordings", RecordingBox.screengrabber.rootDoc);
+            Doc.AddDocToList(Doc.UserDoc(), 'workspaceRecordings', RecordingBox.screengrabber.rootDoc);
         } else {
             //when we first press mic
             const screengrabber = Docs.Create.WebCamDocument('', {
+                title: `${Doc.ActiveDashboard?.title ?? ''} ${new DateField()}`,
                 _width: 205,
                 _height: 115,
             });
             screengrabber.overlayX = 70; //was -400
             screengrabber.overlayY = 590; //was 0
             screengrabber[Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true;
-            Doc.AddToMyOverlay(screengrabber);  //just adds doc to overlay
+            Doc.AddToMyOverlay(screengrabber); //just adds doc to overlay
             DocumentManager.Instance.AddViewRenderedCb(screengrabber, docView => {
                 RecordingBox.screengrabber = docView.ComponentView as RecordingBox;
                 RecordingBox.screengrabber.Record?.();
@@ -120,21 +115,21 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @undoBatch
     @action
     public static toggleWorkspaceRecPlayback(value: Doc) {
-        let docval = undefined;
         Doc.UserDoc().currentRecording = value;
-        console.log(value)
-        value.overlayX =70;
+        console.log(value);
+        value.overlayX = 70;
         value.overlayY = 590;
         if (!Doc.UserDoc().isAddRecToDocMode) {
             Doc.UserDoc().isRecPlayback = true;
             Doc.UserDoc().isWorkspaceRecPlaying = true;
             Doc.AddToMyOverlay(value);
             DocumentManager.Instance.AddViewRenderedCb(value, docView => {
-                Doc.UserDoc().currentRecording = docView.ComponentView as RecordingBox;
-                SelectionManager.SelectSchemaViewDoc(value);    
-        })} else {
-            let recordingIndex = Array.from(Doc.UserDoc().workspaceRecordings).indexOf(value);
-            DragManager.StartDropdownDrag([document.createElement('div')],new DragManager.DocumentDragData([value]), 1, 1, recordingIndex);
+                Doc.UserDoc().currentRecording = docView.rootDoc;
+                SelectionManager.SelectSchemaViewDoc(value);
+            });
+        } else {
+            let recordingIndex = DocListCast(Doc.UserDoc().workspaceRecordings).indexOf(value);
+            DragManager.StartDropdownDrag([document.createElement('div')], new DragManager.DocumentDragData([value]), 1, 1, recordingIndex);
         }
     }
 
@@ -145,11 +140,11 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @undoBatch
     @action
     public static addRecToWorkspace(value: RecordingBox) {
-        console.log("adding rec to doc");
+        console.log('adding rec to doc');
         console.log(value);
-         let ffView = Array.from(DocumentManager.Instance.DocumentViews).find(view => view.ComponentView instanceof CollectionFreeFormView);
+        let ffView = Array.from(DocumentManager.Instance.DocumentViews).find(view => view.ComponentView instanceof CollectionFreeFormView);
         (ffView?.ComponentView as CollectionFreeFormView).props.addDocument?.(value.rootDoc);
-        let recordingIndex = Array.from(Doc.UserDoc().workspaceRecordings).indexOf(value.rootDoc);
+        let recordingIndex = DocListCast(Doc.UserDoc().workspaceRecordings).indexOf(value.rootDoc);
         console.log(recordingIndex);
         Cast(Doc.UserDoc().workspaceRecordings, listSpec(Doc), null)?.splice(recordingIndex, 1);
         Doc.UserDoc().isAddRecToDocMode = false;
@@ -187,13 +182,12 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
         Doc.UserDoc().isWorkspaceRecPlaying = false;
         Doc.UserDoc().isWorkspaceRecPaused = false;
         Doc.RemFromMyOverlay(value.rootDoc);
-
     }
 
     @undoBatch
     @action
     public static removeWorkspaceRec(value: VideoBox) {
-        let recordingIndex = Array.from(Doc.UserDoc().workspaceRecordings).indexOf(value.rootDoc);
+        let recordingIndex = DocListCast(Doc.UserDoc().workspaceRecordings).indexOf(value.rootDoc);
         Cast(Doc.UserDoc().workspaceRecordings, listSpec(Doc), null)?.splice(recordingIndex, 1);
         Doc.UserDoc().isAddRecToDocMode = false;
         Doc.RemFromMyOverlay(value.rootDoc);
@@ -202,11 +196,8 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
         Doc.UserDoc().isAddRecToDocMode = false;
         Doc.UserDoc().isWorkspaceRecPlaying = false;
         Doc.UserDoc().isWorkspaceRecPaused = false;
-
     }
 
-    
-
     Record: undefined | (() => void);
     Pause: undefined | (() => void);
     Finish: undefined | (() => void);
@@ -234,26 +225,50 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     static screengrabber: RecordingBox | undefined;
 }
 
-ScriptingGlobals.add(function toggleRecording(_readOnly_: boolean) { RecordingBox.toggleWorkspaceRecording(_readOnly_); });
-ScriptingGlobals.add(function toggleRecPlayback(value: Doc) { RecordingBox.toggleWorkspaceRecPlayback(value); });
-ScriptingGlobals.add(function addRectoWorkspace(value: RecordingBox) { RecordingBox.addRecToWorkspace(value); });
+ScriptingGlobals.add(function toggleRecording(_readOnly_: boolean) {
+    RecordingBox.toggleWorkspaceRecording(_readOnly_);
+});
+ScriptingGlobals.add(function toggleRecPlayback(value: Doc) {
+    RecordingBox.toggleWorkspaceRecPlayback(value);
+});
+ScriptingGlobals.add(function addRectoWorkspace(value: RecordingBox) {
+    RecordingBox.addRecToWorkspace(value);
+});
 
-ScriptingGlobals.add(function playWorkspaceRec(value: VideoBox) { RecordingBox.playWorkspaceRec(value); });
-ScriptingGlobals.add(function pauseWorkspaceRec(value: VideoBox) { RecordingBox.pauseWorkspaceRec(value); });
-ScriptingGlobals.add(function closeWorkspaceRec(value: VideoBox) { RecordingBox.closeWorkspaceRec(value); });
-ScriptingGlobals.add(function removeWorkspaceRec(value: VideoBox) { RecordingBox.removeWorkspaceRec(value) });
+ScriptingGlobals.add(function playWorkspaceRec(value: VideoBox) {
+    RecordingBox.playWorkspaceRec(value);
+});
+ScriptingGlobals.add(function pauseWorkspaceRec(value: VideoBox) {
+    RecordingBox.pauseWorkspaceRec(value);
+});
+ScriptingGlobals.add(function closeWorkspaceRec(value: VideoBox) {
+    RecordingBox.closeWorkspaceRec(value);
+});
+ScriptingGlobals.add(function removeWorkspaceRec(value: VideoBox) {
+    RecordingBox.removeWorkspaceRec(value);
+});
 
-ScriptingGlobals.add(function getWorkspaceRecordings() { return Doc.UserDoc().workspaceRecordings });
-ScriptingGlobals.add(function getIsRecording() { return Doc.UserDoc().isRecording; })
-ScriptingGlobals.add(function getIsRecPlayback() { return Doc.UserDoc().isRecPlayback; })
-ScriptingGlobals.add(function getCurrentRecording() { return Doc.UserDoc().currentRecording; })
-ScriptingGlobals.add(function getIsWorkspaceRecPlaying() { return Doc.UserDoc().isWorkspaceRecPlaying; })
-ScriptingGlobals.add(function getIsWorkspaceRecPaused() { return Doc.UserDoc().isWorkspaceRecPaused; })
+ScriptingGlobals.add(function getWorkspaceRecordings() {
+    return Doc.UserDoc().workspaceRecordings;
+});
+ScriptingGlobals.add(function getIsRecording() {
+    return Doc.UserDoc().isRecording;
+});
+ScriptingGlobals.add(function getIsRecPlayback() {
+    return Doc.UserDoc().isRecPlayback;
+});
+ScriptingGlobals.add(function getCurrentRecording() {
+    return Doc.UserDoc().currentRecording;
+});
+ScriptingGlobals.add(function getIsWorkspaceRecPlaying() {
+    return Doc.UserDoc().isWorkspaceRecPlaying;
+});
+ScriptingGlobals.add(function getIsWorkspaceRecPaused() {
+    return Doc.UserDoc().isWorkspaceRecPaused;
+});
 ScriptingGlobals.add(function renderDropdown() {
-    if (!Doc.UserDoc().workspaceRecordings || Array.from(Doc.UserDoc().workspaceRecordings).length === 0) {
+    if (!Doc.UserDoc().workspaceRecordings || DocListCast(Doc.UserDoc().workspaceRecordings).length === 0) {
         return true;
     }
     return false;
-})
-
-
+});
-- 
cgit v1.2.3-70-g09d2


From 5651f5428f8464ae0f131c73601b69aba11dff98 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 31 Aug 2023 12:36:33 -0400
Subject: fixed properties view text colors

---
 src/client/views/MainView.tsx             | 2 +-
 src/client/views/collections/TreeView.tsx | 3 ---
 src/client/views/nodes/trails/PresBox.tsx | 2 +-
 3 files changed, 2 insertions(+), 5 deletions(-)

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

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 01a26559c..7ae9a374d 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -809,7 +809,7 @@ export class MainView extends React.Component {
                                 <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={SettingsManager.userColor} size="sm" />
                             </div>
                         )}
-                        <div className="properties-container" style={{ width: this.propertiesWidth() }}>
+                        <div className="properties-container" style={{ width: this.propertiesWidth(), color: SettingsManager.userColor }}>
                             {this.propertiesWidth() < 10 ? null : <PropertiesView styleProvider={DefaultStyleProvider} addDocTab={DocumentViewInternal.addDocTabFunc} width={this.propertiesWidth()} height={this.propertiesHeight()} />}
                         </div>
                     </div>
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 4f9310434..8dd1c8ee8 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -227,7 +227,6 @@ export class TreeView extends React.Component<TreeViewProps> {
     recurToggle = (childList: Doc[]) => {
         if (childList.length > 0) {
             childList.forEach(child => {
-                console.log(child);
                 child.runProcess = !!!child.runProcess;
                 TreeView.ToggleChildrenRun.get(child)?.();
             });
@@ -265,8 +264,6 @@ export class TreeView extends React.Component<TreeViewProps> {
         this._editTitleScript = Doc.IsSystem(this.props.document) ? () => TreeView._openLevelScript! : () => TreeView._openTitleScript!;
 
         // set for child processing highligting
-        // this.dataDoc.testing = 'testing';
-        console.log(this.doc, this.dataDoc, this.childDocs);
         this.dataDoc.hasChildren = this.childDocs.length > 0;
         // this.dataDoc.children = this.childDocs;
         TreeView.ToggleChildrenRun.set(this.doc, () => {
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 7bb1b80a3..92c130ea1 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -1691,7 +1691,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             </div>
         );
         const presDirection = (direction: PresEffectDirection, icon: string, gridColumn: number, gridRow: number, opts: object) => {
-            const color = activeItem.presentation_effectDirection === direction || (direction === PresEffectDirection.Center && !activeItem.presentation_effectDirection) ? Colors.LIGHT_BLUE : 'black';
+            const color = activeItem.presentation_effectDirection === direction || (direction === PresEffectDirection.Center && !activeItem.presentation_effectDirection) ? SettingsManager.userVariantColor : SettingsManager.userColor;
             return (
                 <Tooltip title={<div className="dash-tooltip">{direction}</div>}>
                     <div
-- 
cgit v1.2.3-70-g09d2


From a63ab5802551887f62265d420b7c5e925b5cd7d6 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 5 Sep 2023 01:26:54 -0400
Subject: added ui for specifying wehther to play a/v when following links, and
 cleaned up ui/etc for pres trails.  fixed a bunch of colors in pres
 properties.  fixed a/v anchors to be configs when not adding them to the doc,
 otherwise labels.

---
 src/client/util/DocumentManager.ts                 |   5 +-
 src/client/util/LinkFollower.ts                    |   1 +
 src/client/views/MainView.tsx                      |   2 +-
 src/client/views/PropertiesView.tsx                |  14 +-
 src/client/views/UndoStack.tsx                     |  69 ++++----
 .../collections/CollectionStackedTimeline.tsx      |   6 +-
 src/client/views/collections/TabDocView.tsx        |   6 +-
 src/client/views/nodes/AudioBox.tsx                |  28 +--
 src/client/views/nodes/DocumentView.tsx            |   1 +
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |   1 -
 src/client/views/nodes/VideoBox.tsx                |  13 +-
 src/client/views/nodes/trails/PresBox.scss         |   6 -
 src/client/views/nodes/trails/PresBox.tsx          | 192 ++++++++++++++-------
 src/client/views/selectedDoc/SelectedDocView.tsx   |  61 +++----
 14 files changed, 244 insertions(+), 161 deletions(-)

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

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 28ca37611..bfe0e1b48 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -1,9 +1,9 @@
-import { action, computed, observable, ObservableSet, observe, reaction } from 'mobx';
+import { action, computed, observable, ObservableSet, observe } from 'mobx';
 import { Doc, DocListCast, Opt } from '../../fields/Doc';
 import { AclAdmin, AclEdit, Animation } from '../../fields/DocSymbols';
 import { Id } from '../../fields/FieldSymbols';
 import { listSpec } from '../../fields/Schema';
-import { Cast, DocCast, StrCast } from '../../fields/Types';
+import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types';
 import { AudioField } from '../../fields/URLField';
 import { GetEffectiveAcl } from '../../fields/util';
 import { CollectionViewType } from '../documents/DocumentTypes';
@@ -323,6 +323,7 @@ export class DocumentManager {
             if (docView.ComponentView instanceof FormattedTextBox) docView.ComponentView?.focus(viewSpec, options);
             PresBox.restoreTargetDocView(docView, viewSpec, options.zoomTime ?? 500);
             Doc.linkFollowHighlight(viewSpec ? [docView.rootDoc, viewSpec] : docView.rootDoc, undefined, options.effect);
+            if (options.playMedia) docView.ComponentView?.playFrom?.(NumCast(docView.rootDoc._layout_currentTimecode));
             if (options.playAudio) DocumentManager.playAudioAnno(docView.rootDoc);
             if (options.toggleTarget && (!options.didMove || docView.rootDoc.hidden)) docView.rootDoc.hidden = !docView.rootDoc.hidden;
             if (options.effect) docView.rootDoc[Animation] = options.effect;
diff --git a/src/client/util/LinkFollower.ts b/src/client/util/LinkFollower.ts
index b8fea340f..2fc811b09 100644
--- a/src/client/util/LinkFollower.ts
+++ b/src/client/util/LinkFollower.ts
@@ -73,6 +73,7 @@ export class LinkFollower {
                     const toggleTarget = canToggle && BoolCast(sourceDoc.followLinkToggle);
                     const options: DocFocusOptions = {
                         playAudio: BoolCast(sourceDoc.followLinkAudio),
+                        playMedia: BoolCast(sourceDoc.followLinkVideo),
                         toggleTarget,
                         noSelect: true,
                         willPan: true,
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 7ae9a374d..c8b89c1d5 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -805,7 +805,7 @@ export class MainView extends React.Component {
                         {this.dockingContent}
 
                         {this._hideUI ? null : (
-                            <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ background: SettingsManager.userBackgroundColor, right: this.propertiesWidth() - 1 }}>
+                            <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ background: SettingsManager.userVariantColor, right: this.propertiesWidth() - 1 }}>
                                 <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={SettingsManager.userColor} size="sm" />
                             </div>
                         )}
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 5f9439cbc..01329b482 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -1538,6 +1538,16 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                                 <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
                             </button>
                         </div>
+                        <div className="propertiesView-input inline">
+                            <p>Play Target Video</p>
+                            <button
+                                style={{ background: !this.sourceAnchor?.followLinkVideo ? '' : '#4476f7', borderRadius: 3 }}
+                                onPointerDown={e => this.toggleAnchorProp(e, 'followLinkVideo', this.sourceAnchor)}
+                                onClick={e => e.stopPropagation()}
+                                className="propertiesButton">
+                                <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
+                            </button>
+                        </div>
                         <div className="propertiesView-input inline">
                             <p>Zoom Text Selections</p>
                             <button
@@ -1742,12 +1752,12 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                                         color: SettingsManager.userColor,
                                         backgroundColor: this.openPresVisibilityAndDuration ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
                                     }}>
-                                    &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Visibilty
+                                    &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Visibility
                                     <div className="propertiesView-presentationTrails-title-icon">
                                         <FontAwesomeIcon icon={this.openPresVisibilityAndDuration ? 'caret-down' : 'caret-right'} size="lg" />
                                     </div>
                                 </div>
-                                {this.openPresVisibilityAndDuration ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.visibiltyDurationDropdown}</div> : null}
+                                {this.openPresVisibilityAndDuration ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.visibilityDurationDropdown}</div> : null}
                             </div>
                         )}
                         {!selectedItem ? null : (
diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx
index 47853b5e4..1afd5ad22 100644
--- a/src/client/views/UndoStack.tsx
+++ b/src/client/views/UndoStack.tsx
@@ -8,6 +8,7 @@ import { Doc } from '../../fields/Doc';
 import { Popup, Type, isDark } from 'browndash-components';
 import { Colors } from './global/globalEnums';
 import { SettingsManager } from '../util/SettingsManager';
+import { Tooltip } from '@mui/material';
 
 interface UndoStackProps {
     width?: number;
@@ -22,39 +23,43 @@ export class UndoStack extends React.Component<UndoStackProps> {
         const background = UndoManager.batchCounter.get() ? 'yellow' : SettingsManager.userVariantColor;
         const color = UndoManager.batchCounter.get() ? 'black' : SettingsManager.userColor;
         return this.props.inline && UndoStack.HideInline ? null : (
-            <div className="undoStack-outerContainer">
-                <Popup
-                    text="stack"
-                    color={color}
-                    background={background}
-                    placement={`top-start`}
-                    type={Type.TERT}
-                    popup={
-                        <div
-                            className="undoStack-commandsContainer"
-                            ref={r => r?.scroll({ behavior: 'auto', top: r?.scrollHeight + 20 })}
-                            style={{
-                                background,
-                                color,
-                            }}>
-                            {UndoManager.undoStackNames.map((name, i) => (
-                                <div className="undoStack-resultContainer" key={i}>
-                                    <div className="undoStack-commandString">{StrCast(name).replace(/[^\.]*\./, '')}</div>
-                                </div>
-                            ))}
-                            {Array.from(UndoManager.redoStackNames)
-                                .reverse()
-                                .map((name, i) => (
-                                    <div className="undoStack-resultContainer" key={i}>
-                                        <div className="undoStack-commandString" style={{ fontWeight: 'bold', color: SettingsManager.userBackgroundColor }}>
-                                            {StrCast(name).replace(/[^\.]*\./, '')}
+            <Tooltip title={'undo stack (if it stays yellow, undo is broken - you should reload Dash)'}>
+                <div>
+                    <div className="undoStack-outerContainer">
+                        <Popup
+                            text="stack"
+                            color={color}
+                            background={background}
+                            placement={`top-start`}
+                            type={Type.TERT}
+                            popup={
+                                <div
+                                    className="undoStack-commandsContainer"
+                                    ref={r => r?.scroll({ behavior: 'auto', top: r?.scrollHeight + 20 })}
+                                    style={{
+                                        background,
+                                        color,
+                                    }}>
+                                    {UndoManager.undoStackNames.map((name, i) => (
+                                        <div className="undoStack-resultContainer" key={i}>
+                                            <div className="undoStack-commandString">{StrCast(name).replace(/[^\.]*\./, '')}</div>
                                         </div>
-                                    </div>
-                                ))}
-                        </div>
-                    }
-                />
-            </div>
+                                    ))}
+                                    {Array.from(UndoManager.redoStackNames)
+                                        .reverse()
+                                        .map((name, i) => (
+                                            <div className="undoStack-resultContainer" key={i}>
+                                                <div className="undoStack-commandString" style={{ fontWeight: 'bold', color: SettingsManager.userBackgroundColor }}>
+                                                    {StrCast(name).replace(/[^\.]*\./, '')}
+                                                </div>
+                                            </div>
+                                        ))}
+                                </div>
+                            }
+                        />
+                    </div>
+                </div>
+            </Tooltip>
         );
     }
 }
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index d2be70577..0a5a80936 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -32,7 +32,7 @@ import './CollectionStackedTimeline.scss';
 export type CollectionStackedTimelineProps = {
     Play: () => void;
     Pause: () => void;
-    playLink: (linkDoc: Doc) => void;
+    playLink: (linkDoc: Doc, options: DocFocusOptions) => void;
     playFrom: (seekTimeInSeconds: number, endTime?: number) => void;
     playing: () => boolean;
     setTime: (time: number) => void;
@@ -677,7 +677,7 @@ interface StackedTimelineAnchorProps {
     height: number;
     toTimeline: (screen_delta: number, width: number) => number;
     styleProvider?: (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string) => any;
-    playLink: (linkDoc: Doc) => void;
+    playLink: (linkDoc: Doc, options: DocFocusOptions) => void;
     setTime: (time: number) => void;
     startTag: string;
     endTag: string;
@@ -793,7 +793,7 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
     renderInner = computedFn(function (this: StackedTimelineAnchor, mark: Doc, script: undefined | (() => ScriptField), doublescript: undefined | (() => ScriptField), screenXf: () => Transform, width: () => number, height: () => number) {
         const anchor = observable({ view: undefined as any });
         const focusFunc = (doc: Doc, options: DocFocusOptions): number | undefined => {
-            this.props.playLink(mark);
+            this.props.playLink(mark, options);
             return undefined;
         };
         return {
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index f6acafa95..6cdb84dea 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -278,10 +278,8 @@ export class TabDocView extends React.Component<TabDocViewProps> {
 
             if (pinProps.pinViewport) PresBox.pinDocView(pinDoc, pinProps, anchorDoc ?? doc);
             if (!pinProps?.audioRange && duration !== undefined) {
-                pinDoc.mediaStart = 'manual';
-                pinDoc.mediaStop = 'manual';
-                pinDoc.config_clipStart = NumCast(doc.clipStart);
-                pinDoc.config_clipEnd = NumCast(doc.clipEnd, duration);
+                pinDoc.presentation_mediaStart = 'manual';
+                pinDoc.presentation_mediaStop = 'manual';
             }
             if (pinProps?.activeFrame !== undefined) {
                 pinDoc.config_activeFrame = pinProps?.activeFrame;
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 7c409c38c..50b2432d2 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -8,7 +8,7 @@ import { ComputedField } from '../../../fields/ScriptField';
 import { Cast, DateCast, NumCast } from '../../../fields/Types';
 import { AudioField, nullAudio } from '../../../fields/URLField';
 import { emptyFunction, formatTime, returnFalse, setupMoveUpEvents } from '../../../Utils';
-import { DocUtils } from '../../documents/Documents';
+import { Docs, DocUtils } from '../../documents/Documents';
 import { Networking } from '../../Network';
 import { DragManager } from '../../util/DragManager';
 import { LinkManager } from '../../util/LinkManager';
@@ -20,6 +20,7 @@ import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComp
 import './AudioBox.scss';
 import { FieldView, FieldViewProps } from './FieldView';
 import { PinProps, PresBox } from './trails';
+import { DocFocusOptions } from './DocumentView';
 
 /**
  * AudioBox
@@ -134,16 +135,19 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     }
 
     getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
-        const anchor =
-            CollectionStackedTimeline.createAnchor(
-                this.rootDoc,
-                this.dataDoc,
-                this.annotationKey,
-                this._ele?.currentTime || Cast(this.props.Document._layout_currentTimecode, 'number', null) || (this.mediaState === media_state.Recording ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined),
-                undefined,
-                undefined,
-                addAsAnnotation
-            ) || this.rootDoc;
+        const timecode = Cast(this.layoutDoc._layout_currentTimecode, 'number', null);
+        const anchor = addAsAnnotation
+            ? CollectionStackedTimeline.createAnchor(
+                  this.rootDoc,
+                  this.dataDoc,
+                  this.annotationKey,
+                  this._ele?.currentTime || Cast(this.props.Document._layout_currentTimecode, 'number', null) || (this.mediaState === media_state.Recording ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined),
+                  undefined,
+                  undefined,
+                  addAsAnnotation
+              ) || this.rootDoc
+            : Docs.Create.ConfigDocument({ title: '#' + timecode, _timecodeToShow: timecode, annotationOn: this.rootDoc });
+
         PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), temporal: true } }, this.rootDoc);
         return anchor;
     };
@@ -418,7 +422,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     };
 
     // plays link
-    playLink = (link: Doc) => {
+    playLink = (link: Doc, options: DocFocusOptions) => {
         if (link.annotationOn === this.rootDoc) {
             if (!this.layoutDoc.dontAutoPlayFollowedLinks) {
                 this.playFrom(this.timeline?.anchorStart(link) || 0, this.timeline?.anchorEnd(link));
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 998024cea..f7773ff18 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -100,6 +100,7 @@ export interface DocFocusOptions {
     effect?: Doc; // animation effect for focus
     noSelect?: boolean; // whether target should be selected after focusing
     playAudio?: boolean; // whether to play audio annotation on focus
+    playMedia?: boolean; // whether to play start target videos
     openLocation?: OpenWhere; // where to open a missing document
     zoomTextSelections?: boolean; // whether to display a zoomed overlay of anchor text selections
     toggleTarget?: boolean; // whether to toggle target on and off
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index ea7c2de82..1eb6fd51c 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -19,7 +19,6 @@ import { SelectedDocView } from '../../selectedDoc';
 import { StyleProp } from '../../StyleProvider';
 import { OpenWhere } from '../DocumentView';
 import { FieldView, FieldViewProps } from '../FieldView';
-import { RichTextMenu } from '../formattedText/RichTextMenu';
 import './FontIconBox.scss';
 import TrailsIcon from './TrailsIcon';
 
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 56508abf6..9d9aa8a4b 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -29,7 +29,7 @@ import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComp
 import { MarqueeAnnotator } from '../MarqueeAnnotator';
 import { AnchorMenu } from '../pdf/AnchorMenu';
 import { StyleProp } from '../StyleProvider';
-import { DocumentView, OpenWhere } from './DocumentView';
+import { DocFocusOptions, DocumentView, OpenWhere } from './DocumentView';
 import { FieldView, FieldViewProps } from './FieldView';
 import { RecordingBox } from './RecordingBox';
 import { PinProps, PresBox } from './trails';
@@ -385,7 +385,9 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         const timecode = Cast(this.layoutDoc._layout_currentTimecode, 'number', null);
         const marquee = AnchorMenu.Instance.GetAnchor?.(undefined, addAsAnnotation);
         if (!addAsAnnotation && marquee) marquee.backgroundColor = 'transparent';
-        const anchor = CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey, timecode ? timecode : undefined, undefined, marquee, addAsAnnotation) || this.rootDoc;
+        const anchor = addAsAnnotation
+            ? CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey, timecode ? timecode : undefined, undefined, marquee, addAsAnnotation) || this.rootDoc
+            : Docs.Create.ConfigDocument({ title: '#' + timecode, _timecodeToShow: timecode, annotationOn: this.rootDoc });
         PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), temporal: true } }, this.rootDoc);
         return anchor;
     };
@@ -846,11 +848,11 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     zoom = (zoom: number) => this.timeline?.setZoom(zoom);
 
     // plays link
-    playLink = (doc: Doc) => {
-        const startTime = Math.max(0, this._stackedTimeline?.anchorStart(doc) || 0);
+    playLink = (doc: Doc, options: DocFocusOptions) => {
+        const startTime = Math.max(0, NumCast(doc.config_clipStart, this._stackedTimeline?.anchorStart(doc) || 0));
         const endTime = this.timeline?.anchorEnd(doc);
         if (startTime !== undefined) {
-            if (!this.layoutDoc.dontAutoPlayFollowedLinks) endTime ? this.playFrom(startTime, endTime) : this.playFrom(startTime);
+            if (options.playMedia) endTime ? this.playFrom(startTime, endTime) : this.playFrom(startTime);
             else this.Seek(startTime);
         }
     };
@@ -1038,7 +1040,6 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         this.props.bringToFront(cropping);
         return cropping;
     };
-
     savedAnnotations = () => this._savedAnnotations;
     render() {
         const borderRad = this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BorderRounding);
diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss
index bf56b4d9e..31a003144 100644
--- a/src/client/views/nodes/trails/PresBox.scss
+++ b/src/client/views/nodes/trails/PresBox.scss
@@ -187,9 +187,6 @@
         font-size: 11;
         font-weight: 200;
         height: 20;
-        background-color: $white;
-        color: $black;
-        border: solid 1px $black;
         display: flex;
         margin-left: 5px;
         margin-top: 5px;
@@ -210,13 +207,11 @@
 
         .ribbon-propertyUpDownItem {
             cursor: pointer;
-            color: white;
             display: flex;
             justify-content: center;
             align-items: center;
             height: 100%;
             width: 100%;
-            background: $black;
         }
 
         .ribbon-propertyUpDownItem:hover {
@@ -609,7 +604,6 @@
         font-weight: 200;
         height: 20;
         background-color: $white;
-        border: solid 1px rgba(0, 0, 0, 0.5);
         display: flex;
         color: $black;
         margin-top: 5px;
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 92c130ea1..48f376075 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -391,11 +391,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             if (from?.mediaStopTriggerList && this.layoutDoc.presentation_status !== PresStatus.Edit) {
                 DocListCast(from.mediaStopTriggerList).forEach(this.stopTempMedia);
             }
-            if (from?.mediaStop === 'auto' && this.layoutDoc.presentation_status !== PresStatus.Edit) {
+            if (from?.presentation_mediaStop === 'auto' && this.layoutDoc.presentation_status !== PresStatus.Edit) {
                 this.stopTempMedia(from.presentation_targetDoc);
             }
             // If next slide is audio / video 'Play automatically' then the next slide should be played
-            if (this.layoutDoc.presentation_status !== PresStatus.Edit && (this.targetDoc.type === DocumentType.AUDIO || this.targetDoc.type === DocumentType.VID) && this.activeItem.mediaStart === 'auto') {
+            if (this.layoutDoc.presentation_status !== PresStatus.Edit && (this.targetDoc.type === DocumentType.AUDIO || this.targetDoc.type === DocumentType.VID) && this.activeItem.presentation_mediaStart === 'auto') {
                 this.startTempMedia(this.targetDoc, this.activeItem);
             }
             if (!group) this.clearSelectedArray();
@@ -798,8 +798,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             easeFunc: StrCast(activeItem.presEaseFunc, 'ease') as any,
             zoomTextSelections: BoolCast(activeItem.presentation_zoomText),
             playAudio: BoolCast(activeItem.presPlayAudio),
+            playMedia: activeItem.presentation_mediaStart === 'auto',
         };
-        if (activeItem.presOpenInLightbox) {
+        if (activeItem.presentation_openInLightbox) {
             const context = DocCast(targetDoc.annotationOn) ?? targetDoc;
             if (!DocumentManager.Instance.getLightboxDocumentView(context)) {
                 LightboxView.SetLightboxDoc(context);
@@ -1075,8 +1076,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             if (doc.type === DocumentType.LABEL) {
                 const audio = Cast(doc.annotationOn, Doc, null);
                 if (audio) {
-                    audio.mediaStart = 'manual';
-                    audio.mediaStop = 'manual';
                     audio.config_clipStart = NumCast(doc._timecodeToShow /* audioStart */, NumCast(doc._timecodeToShow /* videoStart */));
                     audio.config_clipEnd = NumCast(doc._timecodeToHide /* audioEnd */, NumCast(doc._timecodeToHide /* videoEnd */));
                     audio.presentation_duration = audio.config_clipStart - audio.config_clipEnd;
@@ -1472,8 +1471,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @undoBatch
     @action
     updateOpenDoc = (activeItem: Doc) => {
-        activeItem.presOpenInLightbox = !activeItem.presOpenInLightbox;
-        this.selectedArray.forEach(doc => (doc.presOpenInLightbox = activeItem.presOpenInLightbox));
+        activeItem.presentation_openInLightbox = !activeItem.presentation_openInLightbox;
+        this.selectedArray.forEach(doc => (doc.presentation_openInLightbox = activeItem.presentation_openInLightbox));
     };
 
     @undoBatch
@@ -1501,7 +1500,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 max={max}
                 value={value}
                 readOnly={true}
-                style={{ marginLeft: hmargin, marginRight: hmargin, width: `calc(100% - ${2 * (hmargin ?? 0)}px)` }}
+                style={{ marginLeft: hmargin, marginRight: hmargin, width: `calc(100% - ${2 * (hmargin ?? 0)}px)`, background: SettingsManager.userColor, color: SettingsManager.userVariantColor }}
                 className={`toolbar-slider ${active ? '' : 'none'}`}
                 onPointerDown={e => {
                     PresBox._sliderBatch = UndoManager.StartBatch('pres slider');
@@ -1532,7 +1531,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         });
     };
 
-    @computed get visibiltyDurationDropdown() {
+    @computed get visibilityDurationDropdown() {
         const activeItem = this.activeItem;
         if (activeItem && this.targetDoc) {
             const targetType = this.targetDoc.type;
@@ -1541,30 +1540,49 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             return (
                 <div className="presBox-ribbon">
                     <div className="ribbon-doubleButton">
-                        <Tooltip title={<div className="dash-tooltip">{'Hide before presented'}</div>}>
-                            <div className={`ribbon-toggle ${activeItem.presentation_hideBefore ? 'active' : ''}`} onClick={() => this.updateHideBefore(activeItem)}>
+                        <Tooltip title={<div className="dash-tooltip">Hide before presented</div>}>
+                            <div
+                                className={`ribbon-toggle ${activeItem.presentation_hideBefore ? 'active' : ''}`}
+                                style={{ border: `solid 1px ${SettingsManager.userColor}`, color: SettingsManager.userColor, background: activeItem.presentation_hideBefore ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}
+                                onClick={() => this.updateHideBefore(activeItem)}>
                                 Hide before
                             </div>
                         </Tooltip>
                         <Tooltip title={<div className="dash-tooltip">{'Hide while presented'}</div>}>
-                            <div className={`ribbon-toggle ${activeItem.presentation_hide ? 'active' : ''}`} onClick={() => this.updateHide(activeItem)}>
+                            <div
+                                className={`ribbon-toggle ${activeItem.presentation_hide ? 'active' : ''}`}
+                                style={{ border: `solid 1px ${SettingsManager.userColor}`, color: SettingsManager.userColor, background: activeItem.presentation_hide ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}
+                                onClick={() => this.updateHide(activeItem)}>
                                 Hide
                             </div>
                         </Tooltip>
 
                         <Tooltip title={<div className="dash-tooltip">{'Hide after presented'}</div>}>
-                            <div className={`ribbon-toggle ${activeItem.presentation_hideAfter ? 'active' : ''}`} onClick={() => this.updateHideAfter(activeItem)}>
+                            <div
+                                className={`ribbon-toggle ${activeItem.presentation_hideAfter ? 'active' : ''}`}
+                                style={{ border: `solid 1px ${SettingsManager.userColor}`, color: SettingsManager.userColor, background: activeItem.presentation_hideAfter ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}
+                                onClick={() => this.updateHideAfter(activeItem)}>
                                 Hide after
                             </div>
                         </Tooltip>
 
                         <Tooltip title={<div className="dash-tooltip">{'Open in lightbox view'}</div>}>
-                            <div className="ribbon-toggle" style={{ backgroundColor: activeItem.presOpenInLightbox ? Colors.LIGHT_BLUE : '' }} onClick={() => this.updateOpenDoc(activeItem)}>
+                            <div
+                                className="ribbon-toggle"
+                                style={{
+                                    border: `solid 1px ${SettingsManager.userColor}`,
+                                    color: SettingsManager.userColor,
+                                    background: activeItem.presentation_openInLightbox ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
+                                }}
+                                onClick={() => this.updateOpenDoc(activeItem)}>
                                 Lightbox
                             </div>
                         </Tooltip>
-                        <Tooltip title={<div className="dash-tooltip">{'Transition movement style'}</div>}>
-                            <div className="ribbon-toggle" onClick={() => this.updateEaseFunc(activeItem)}>
+                        <Tooltip title={<div className="dash-tooltip">Transition movement style</div>}>
+                            <div
+                                className="ribbon-toggle"
+                                style={{ border: `solid 1px ${SettingsManager.userColor}`, color: SettingsManager.userColor, background: activeItem.presEaseFunc === 'ease' ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}
+                                onClick={() => this.updateEaseFunc(activeItem)}>
                                 {`${StrCast(activeItem.presEaseFunc, 'ease')}`}
                             </div>
                         </Tooltip>
@@ -1573,10 +1591,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         <>
                             <div className="ribbon-doubleButton">
                                 <div className="presBox-subheading">Slide Duration</div>
-                                <div className="ribbon-property">
+                                <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}>
                                     <input className="presBox-input" type="number" readOnly={true} value={duration} onKeyDown={e => e.stopPropagation()} onChange={e => this.updateDurationTime(e.target.value)} /> s
                                 </div>
-                                <div className="ribbon-propertyUpDown">
+                                <div className="ribbon-propertyUpDown" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userColor }}>
                                     <div className="ribbon-propertyUpDownItem" onClick={() => this.updateDurationTime(String(duration), 1000)}>
                                         <FontAwesomeIcon icon={'caret-up'} />
                                     </div>
@@ -1615,7 +1633,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         <div className="presBox-subheading">Progressivize Collection</div>
                         <input
                             className="presBox-checkbox"
-                            style={{ margin: 10 }}
+                            style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
                             type="checkbox"
                             onChange={() => {
                                 activeItem.presentation_indexed = activeItem.presentation_indexed === undefined ? 0 : undefined;
@@ -1638,7 +1656,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         <div className="presBox-subheading">Progressivize First Bullet</div>
                         <input
                             className="presBox-checkbox"
-                            style={{ margin: 10 }}
+                            style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
                             type="checkbox"
                             onChange={() => (activeItem.presentation_indexedStart = activeItem.presentation_indexedStart ? 0 : 1)}
                             checked={!NumCast(activeItem.presentation_indexedStart)}
@@ -1646,7 +1664,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     </div>
                     <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
                         <div className="presBox-subheading">Expand Current Bullet</div>
-                        <input className="presBox-checkbox" style={{ margin: 10 }} type="checkbox" onChange={() => (activeItem.presBulletExpand = !activeItem.presBulletExpand)} checked={BoolCast(activeItem.presBulletExpand)} />
+                        <input
+                            className="presBox-checkbox"
+                            style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
+                            type="checkbox"
+                            onChange={() => (activeItem.presBulletExpand = !activeItem.presBulletExpand)}
+                            checked={BoolCast(activeItem.presBulletExpand)}
+                        />
                     </div>
 
                     <div className="ribbon-box">
@@ -1657,10 +1681,18 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 e.stopPropagation();
                                 this._openBulletEffectDropdown = !this._openBulletEffectDropdown;
                             })}
-                            style={{ borderBottomLeftRadius: this._openBulletEffectDropdown ? 0 : 5, border: this._openBulletEffectDropdown ? `solid 2px ${Colors.MEDIUM_BLUE}` : 'solid 1px black' }}>
+                            style={{
+                                color: SettingsManager.userColor,
+                                background: SettingsManager.userVariantColor,
+                                borderBottomLeftRadius: this._openBulletEffectDropdown ? 0 : 5,
+                                border: this._openBulletEffectDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`,
+                            }}>
                             {effect?.toString()}
                             <FontAwesomeIcon className="presBox-dropdownIcon" style={{ gridColumn: 2, color: this._openBulletEffectDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={'angle-down'} />
-                            <div className={'presBox-dropdownOptions'} style={{ display: this._openBulletEffectDropdown ? 'grid' : 'none' }} onPointerDown={e => e.stopPropagation()}>
+                            <div
+                                className={'presBox-dropdownOptions'}
+                                style={{ display: this._openBulletEffectDropdown ? 'grid' : 'none', color: SettingsManager.userColor, background: SettingsManager.userBackgroundColor }}
+                                onPointerDown={e => e.stopPropagation()}>
                                 {bulletEffect(PresEffect.None)}
                                 {bulletEffect(PresEffect.Fade)}
                                 {bulletEffect(PresEffect.Flip)}
@@ -1725,7 +1757,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 e.stopPropagation();
                                 this._openMovementDropdown = !this._openMovementDropdown;
                             })}
-                            style={{ borderBottomLeftRadius: this._openMovementDropdown ? 0 : 5, border: this._openMovementDropdown ? `solid 2px ${Colors.MEDIUM_BLUE}` : 'solid 1px black' }}>
+                            style={{
+                                color: SettingsManager.userColor,
+                                background: SettingsManager.userVariantColor,
+                                borderBottomLeftRadius: this._openMovementDropdown ? 0 : 5,
+                                border: this._openMovementDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`,
+                            }}>
                             {this.movementName(activeItem)}
                             <FontAwesomeIcon className="presBox-dropdownIcon" style={{ gridColumn: 2, color: this._openMovementDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={'angle-down'} />
                             <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onPointerDown={StopEvent} style={{ display: this._openMovementDropdown ? 'grid' : 'none' }}>
@@ -1738,10 +1775,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         </div>
                         <div className="ribbon-doubleButton" style={{ display: activeItem.presentation_movement === PresMovement.Zoom ? 'inline-flex' : 'none' }}>
                             <div className="presBox-subheading">Zoom (% screen filled)</div>
-                            <div className="ribbon-property">
+                            <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}>
                                 <input className="presBox-input" type="number" readOnly={true} value={zoom} onChange={e => this.updateZoom(e.target.value)} />%
                             </div>
-                            <div className="ribbon-propertyUpDown">
+                            <div className="ribbon-propertyUpDown" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userColor }}>
                                 <div className="ribbon-propertyUpDownItem" onClick={() => this.updateZoom(String(zoom), 0.1)}>
                                     <FontAwesomeIcon icon={'caret-up'} />
                                 </div>
@@ -1753,10 +1790,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         {PresBox.inputter('0', '1', '100', zoom, activeItem.presentation_movement === PresMovement.Zoom, this.updateZoom)}
                         <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
                             <div className="presBox-subheading">Transition Time</div>
-                            <div className="ribbon-property">
+                            <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}>
                                 <input className="presBox-input" type="number" readOnly={true} value={transitionSpeed} onKeyDown={e => e.stopPropagation()} onChange={action(e => this.updateTransitionTime(e.target.value))} /> s
                             </div>
-                            <div className="ribbon-propertyUpDown">
+                            <div className="ribbon-propertyUpDown" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userColor }}>
                                 <div className="ribbon-propertyUpDownItem" onClick={() => this.updateTransitionTime(String(transitionSpeed), 1000)}>
                                     <FontAwesomeIcon icon={'caret-up'} />
                                 </div>
@@ -1776,13 +1813,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         Effects
                         <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
                             <div className="presBox-subheading">Play Audio Annotation</div>
-                            <input className="presBox-checkbox" style={{ margin: 10 }} type="checkbox" onChange={() => (activeItem.presPlayAudio = !BoolCast(activeItem.presPlayAudio))} checked={BoolCast(activeItem.presPlayAudio)} />
+                            <input
+                                className="presBox-checkbox"
+                                style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
+                                type="checkbox"
+                                onChange={() => (activeItem.presPlayAudio = !BoolCast(activeItem.presPlayAudio))}
+                                checked={BoolCast(activeItem.presPlayAudio)}
+                            />
                         </div>
                         <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
                             <div className="presBox-subheading">Zoom Text Selections</div>
                             <input
                                 className="presBox-checkbox"
-                                style={{ margin: 10 }}
+                                style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
                                 type="checkbox"
                                 onChange={() => (activeItem.presentation_zoomText = !BoolCast(activeItem.presentation_zoomText))}
                                 checked={BoolCast(activeItem.presentation_zoomText)}
@@ -1794,7 +1837,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 e.stopPropagation();
                                 this._openEffectDropdown = !this._openEffectDropdown;
                             })}
-                            style={{ borderBottomLeftRadius: this._openEffectDropdown ? 0 : 5, border: this._openEffectDropdown ? `solid 2px ${Colors.MEDIUM_BLUE}` : 'solid 1px black' }}>
+                            style={{
+                                color: SettingsManager.userColor,
+                                background: SettingsManager.userVariantColor,
+                                borderBottomLeftRadius: this._openEffectDropdown ? 0 : 5,
+                                border: this._openEffectDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`,
+                            }}>
                             {effect?.toString()}
                             <FontAwesomeIcon className="presBox-dropdownIcon" style={{ gridColumn: 2, color: this._openEffectDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={'angle-down'} />
                             <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} style={{ display: this._openEffectDropdown ? 'grid' : 'none' }} onPointerDown={e => e.stopPropagation()}>
@@ -1808,7 +1856,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         </div>
                         <div className="ribbon-doubleButton" style={{ display: effect === PresEffectDirection.None ? 'none' : 'inline-flex' }}>
                             <div className="presBox-subheading">Effect direction</div>
-                            <div className="ribbon-property">{StrCast(this.activeItem.presentation_effectDirection)}</div>
+                            <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}>
+                                {StrCast(this.activeItem.presentation_effectDirection)}
+                            </div>
                         </div>
                         <div className="effectDirection" style={{ display: effect === PresEffectDirection.None ? 'none' : 'grid', width: 40 }}>
                             {presDirection(PresEffectDirection.Left, 'angle-right', 1, 2, {})}
@@ -1830,8 +1880,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @computed get mediaOptionsDropdown() {
         const activeItem = this.activeItem;
         if (activeItem && this.targetDoc) {
-            const clipStart = NumCast(activeItem.clipStart);
-            const clipEnd = NumCast(activeItem.clipEnd, NumCast(activeItem[Doc.LayoutFieldKey(activeItem) + '_duration']));
+            const renderTarget = PresBox.targetRenderedDoc(this.activeItem);
+            const clipStart = NumCast(renderTarget.clipStart);
+            const clipEnd = NumCast(renderTarget.clipEnd, clipStart + NumCast(renderTarget[Doc.LayoutFieldKey(renderTarget) + '_duration']));
+            const config_clipEnd = NumCast(activeItem.config_clipEnd) < NumCast(activeItem.config_clipStart) ? clipEnd - clipStart : NumCast(activeItem.config_clipEnd);
             return (
                 <div className={'presBox-ribbon'} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
                     <div>
@@ -1842,7 +1894,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                     <div className="slider-text" style={{ fontWeight: 500 }}>
                                         Start time (s)
                                     </div>
-                                    <div id={'startTime'} className="slider-number" style={{ backgroundColor: Colors.LIGHT_GRAY }}>
+                                    <div id="startTime" className="slider-number" style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}>
                                         <input
                                             className="presBox-input"
                                             style={{ textAlign: 'center', width: '100%', height: 15, fontSize: 10 }}
@@ -1850,9 +1902,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                             readOnly={true}
                                             value={NumCast(activeItem.config_clipStart).toFixed(2)}
                                             onKeyDown={e => e.stopPropagation()}
-                                            onChange={action((e: React.ChangeEvent<HTMLInputElement>) => {
-                                                activeItem.config_clipStart = Number(e.target.value);
-                                            })}
+                                            onChange={action(e => (activeItem.config_clipStart = Number(e.target.value)))}
                                         />
                                     </div>
                                 </div>
@@ -1860,25 +1910,23 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                     <div className="slider-text" style={{ fontWeight: 500 }}>
                                         Duration (s)
                                     </div>
-                                    <div className="slider-number" style={{ backgroundColor: Colors.LIGHT_BLUE }}>
-                                        {Math.round((NumCast(activeItem.config_clipEnd) - NumCast(activeItem.config_clipStart)) * 10) / 10}
+                                    <div className="slider-number" style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}>
+                                        {Math.round((config_clipEnd - NumCast(activeItem.config_clipStart)) * 10) / 10}
                                     </div>
                                 </div>
                                 <div className="slider-block">
                                     <div className="slider-text" style={{ fontWeight: 500 }}>
                                         End time (s)
                                     </div>
-                                    <div id={'endTime'} className="slider-number" style={{ backgroundColor: Colors.LIGHT_GRAY }}>
+                                    <div id="endTime" className="slider-number" style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}>
                                         <input
                                             className="presBox-input"
                                             onKeyDown={e => e.stopPropagation()}
                                             style={{ textAlign: 'center', width: '100%', height: 15, fontSize: 10 }}
                                             type="number"
                                             readOnly={true}
-                                            value={NumCast(activeItem.config_clipEnd).toFixed(2)}
-                                            onChange={action((e: React.ChangeEvent<HTMLInputElement>) => {
-                                                activeItem.config_clipEnd = Number(e.target.value);
-                                            })}
+                                            value={config_clipEnd.toFixed(2)}
+                                            onChange={action(e => (activeItem.config_clipEnd = Number(e.target.value)))}
                                         />
                                     </div>
                                 </div>
@@ -1889,16 +1937,15 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                     step="0.1"
                                     min={clipStart}
                                     max={clipEnd}
-                                    value={NumCast(activeItem.config_clipEnd)}
-                                    style={{ gridColumn: 1, gridRow: 1 }}
+                                    value={config_clipEnd}
+                                    style={{ gridColumn: 1, gridRow: 1, background: SettingsManager.userColor, color: SettingsManager.userVariantColor }}
                                     className={`toolbar-slider ${'end'}`}
                                     id="toolbar-slider"
                                     onPointerDown={e => {
                                         this._batch = UndoManager.StartBatch('config_clipEnd');
                                         const endBlock = document.getElementById('endTime');
                                         if (endBlock) {
-                                            endBlock.style.color = Colors.LIGHT_GRAY;
-                                            endBlock.style.backgroundColor = Colors.MEDIUM_BLUE;
+                                            endBlock.style.backgroundColor = SettingsManager.userVariantColor;
                                         }
                                         e.stopPropagation();
                                     }}
@@ -1906,8 +1953,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                         this._batch?.end();
                                         const endBlock = document.getElementById('endTime');
                                         if (endBlock) {
-                                            endBlock.style.color = Colors.BLACK;
-                                            endBlock.style.backgroundColor = Colors.LIGHT_GRAY;
+                                            endBlock.style.backgroundColor = SettingsManager.userBackgroundColor;
                                         }
                                     }}
                                     onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
@@ -1928,8 +1974,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                         this._batch = UndoManager.StartBatch('config_clipStart');
                                         const startBlock = document.getElementById('startTime');
                                         if (startBlock) {
-                                            startBlock.style.color = Colors.LIGHT_GRAY;
-                                            startBlock.style.backgroundColor = Colors.MEDIUM_BLUE;
+                                            startBlock.style.backgroundColor = SettingsManager.userVariantColor;
                                         }
                                         e.stopPropagation();
                                     }}
@@ -1937,8 +1982,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                         this._batch?.end();
                                         const startBlock = document.getElementById('startTime');
                                         if (startBlock) {
-                                            startBlock.style.color = Colors.BLACK;
-                                            startBlock.style.backgroundColor = Colors.LIGHT_GRAY;
+                                            startBlock.style.backgroundColor = SettingsManager.userBackgroundColor;
                                         }
                                     }}
                                     onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
@@ -1958,22 +2002,46 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                             <div className="presBox-subheading">Start playing:</div>
                             <div className="presBox-radioButtons">
                                 <div className="checkbox-container">
-                                    <input className="presBox-checkbox" type="checkbox" onChange={() => (activeItem.mediaStart = 'manual')} checked={activeItem.mediaStart === 'manual'} />
+                                    <input
+                                        className="presBox-checkbox"
+                                        type="checkbox"
+                                        style={{ border: `solid 1px ${SettingsManager.userColor}` }}
+                                        onChange={() => (activeItem.presentation_mediaStart = 'manual')}
+                                        checked={activeItem.presentation_mediaStart === 'manual'}
+                                    />
                                     <div>On click</div>
                                 </div>
                                 <div className="checkbox-container">
-                                    <input className="presBox-checkbox" type="checkbox" onChange={() => (activeItem.mediaStart = 'auto')} checked={activeItem.mediaStart === 'auto'} />
+                                    <input
+                                        className="presBox-checkbox"
+                                        style={{ border: `solid 1px ${SettingsManager.userColor}` }}
+                                        type="checkbox"
+                                        onChange={() => (activeItem.presentation_mediaStart = 'auto')}
+                                        checked={activeItem.presentation_mediaStart === 'auto'}
+                                    />
                                     <div>Automatically</div>
                                 </div>
                             </div>
                             <div className="presBox-subheading">Stop playing:</div>
                             <div className="presBox-radioButtons">
                                 <div className="checkbox-container">
-                                    <input className="presBox-checkbox" type="checkbox" onChange={() => (activeItem.mediaStop = 'manual')} checked={activeItem.mediaStop === 'manual'} />
-                                    <div>At audio end time</div>
+                                    <input
+                                        className="presBox-checkbox"
+                                        type="checkbox"
+                                        style={{ border: `solid 1px ${SettingsManager.userColor}` }}
+                                        onChange={() => (activeItem.presentation_mediaStop = 'manual')}
+                                        checked={activeItem.presentation_mediaStop === 'manual'}
+                                    />
+                                    <div>At media end time</div>
                                 </div>
                                 <div className="checkbox-container">
-                                    <input className="presBox-checkbox" type="checkbox" onChange={() => (activeItem.mediaStop = 'auto')} checked={activeItem.mediaStop === 'auto'} />
+                                    <input
+                                        className="presBox-checkbox"
+                                        type="checkbox"
+                                        style={{ border: `solid 1px ${SettingsManager.userColor}` }}
+                                        onChange={() => (activeItem.presentation_mediaStop = 'auto')}
+                                        checked={activeItem.presentation_mediaStop === 'auto'}
+                                    />
                                     <div>On slide change</div>
                                 </div>
                                 {/* <div className="checkbox-container">
@@ -2221,8 +2289,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         const propTitle = SettingsManager.propertiesWidth > 0 ? 'Close Presentation Panel' : 'Open Presentation Panel';
         const mode = StrCast(this.rootDoc._type_collection) as CollectionViewType;
         const isMini: boolean = this.toolbarWidth <= 100;
-        const activeColor = Colors.LIGHT_BLUE;
-        const inactiveColor = Colors.WHITE;
+        const activeColor = SettingsManager.userVariantColor;
+        const inactiveColor = SettingsManager.userColor;
         return mode === CollectionViewType.Carousel3D || Doc.IsInMyOverlay(this.rootDoc) ? null : (
             <div id="toolbarContainer" className={'presBox-toolbar'}>
                 {/* <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={action(() => this.newDocumentTools = !this.newDocumentTools)}>
diff --git a/src/client/views/selectedDoc/SelectedDocView.tsx b/src/client/views/selectedDoc/SelectedDocView.tsx
index 955a4a174..2139919e0 100644
--- a/src/client/views/selectedDoc/SelectedDocView.tsx
+++ b/src/client/views/selectedDoc/SelectedDocView.tsx
@@ -1,12 +1,14 @@
 import React = require('react');
-import { Doc } from "../../../fields/Doc";
-import { observer } from "mobx-react";
-import { computed } from "mobx";
-import { StrCast } from "../../../fields/Types";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Colors, ListBox } from 'browndash-components';
+import { ListBox } from 'browndash-components';
+import { computed } from 'mobx';
+import { observer } from 'mobx-react';
+import { Doc } from '../../../fields/Doc';
+import { StrCast } from '../../../fields/Types';
 import { DocumentManager } from '../../util/DocumentManager';
 import { DocFocusOptions } from '../nodes/DocumentView';
+import { emptyFunction } from '../../../Utils';
+import { SettingsManager } from '../../util/SettingsManager';
 
 export interface SelectedDocViewProps {
     selectedDocs: Doc[];
@@ -14,34 +16,33 @@ export interface SelectedDocViewProps {
 
 @observer
 export class SelectedDocView extends React.Component<SelectedDocViewProps> {
-
     @computed get selectedDocs() {
         return this.props.selectedDocs;
     }
-    
 
     render() {
-        return <div className={`selectedDocView-container`}>
-            <ListBox
-                items={this.selectedDocs.map((doc) => {
-                    const icon = Doc.toIcon(doc);
-                    const iconEle = <FontAwesomeIcon size={'1x'} icon={icon} />;
-                    const text = StrCast(doc.title)
-                    const finished = () => {
-                        
-                    };
-                    const options: DocFocusOptions = {
-                        playAudio: false,
-                    };
-                    return {
-                        text: text,
-                        val: StrCast(doc._id),
-                        icon: iconEle,
-                        onClick: () => {DocumentManager.Instance.showDocument(doc, options, finished);}
-                    }
-                })}
-                color={StrCast(Doc.UserDoc().userColor)}
-            />
-        </div>
+        return (
+            <div className="selectedDocView-container">
+                <ListBox
+                    items={this.selectedDocs.map(doc => {
+                        const options: DocFocusOptions = {
+                            playAudio: false,
+                            playMedia: false,
+                            willPan: true,
+                        };
+                        return {
+                            text: StrCast(doc.title),
+                            val: StrCast(doc._id),
+                            color: SettingsManager.userColor,
+                            background: SettingsManager.userBackgroundColor,
+                            icon: <FontAwesomeIcon size={'1x'} icon={Doc.toIcon(doc)} />,
+                            onClick: () => DocumentManager.Instance.showDocument(doc, options, emptyFunction),
+                        };
+                    })}
+                    color={SettingsManager.userColor}
+                    background={SettingsManager.userBackgroundColor}
+                />
+            </div>
+        );
     }
-}
\ No newline at end of file
+}
-- 
cgit v1.2.3-70-g09d2


From 530294ae0b4721f07ddbfdd584ed91ff07cdc5e3 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 6 Sep 2023 12:11:23 -0400
Subject: added undo for removing dashboards and add to recently closed. fixed
 link menu to open up link editor more direclty

---
 src/client/util/CurrentUserUtils.ts                |  2 +-
 src/client/util/RTFMarkup.tsx                      |  2 +-
 src/client/util/SelectionManager.ts                |  5 +-
 src/client/util/ServerStats.tsx                    |  2 +-
 src/client/views/DashboardView.tsx                 | 12 ++--
 src/client/views/MainView.tsx                      |  2 +-
 .../views/PropertiesDocBacklinksSelector.tsx       |  7 ++-
 src/client/views/PropertiesView.scss               |  6 ++
 src/client/views/PropertiesView.tsx                | 71 ++++++++++++++--------
 src/client/views/collections/TabDocView.tsx        |  4 +-
 src/client/views/linking/LinkMenuItem.tsx          | 15 +++--
 11 files changed, 81 insertions(+), 47 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index af0f62c0f..836160265 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -488,7 +488,7 @@ export class CurrentUserUtils {
         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, undefined as any];// entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuScripts
+        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 reqdOpts:DocumentOptions = {
diff --git a/src/client/util/RTFMarkup.tsx b/src/client/util/RTFMarkup.tsx
index 78069d323..9dd14a3c3 100644
--- a/src/client/util/RTFMarkup.tsx
+++ b/src/client/util/RTFMarkup.tsx
@@ -33,7 +33,7 @@ export class RTFMarkup extends React.Component<{}> {
      */
     @computed get cheatSheet() {
         return (
-            <div style={{ background: SettingsManager.Instance?.userBackgroundColor, color: SettingsManager.Instance?.userColor, textAlign: 'initial', height: '100%' }}>
+            <div style={{ background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor, textAlign: 'initial', height: '100%' }}>
                 <p>
                     <b style={{ fontSize: 'larger' }}>{`wiki:phrase`}</b>
                     {` display wikipedia page for entered text (terminate with carriage return)`}
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index dbf33fcf5..d0f66d124 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -26,9 +26,6 @@ export namespace SelectionManager {
             // if doc is not in SelectedDocuments, add it
             if (!manager.SelectedViewsMap.get(docView)) {
                 if (!ctrlPressed) {
-                    if (LinkManager.currentLink && !LinkManager.Links(docView.rootDoc).includes(LinkManager.currentLink) && docView.rootDoc !== LinkManager.currentLink) {
-                        LinkManager.currentLink = undefined;
-                    }
                     this.DeselectAll();
                 }
 
@@ -54,6 +51,8 @@ export namespace SelectionManager {
         }
         @action
         DeselectAll(): void {
+            LinkManager.currentLink = undefined;
+            LinkManager.currentLinkAnchor = undefined;
             manager.SelectedSchemaDocument = undefined;
             Array.from(manager.SelectedViewsMap.keys()).forEach(dv => dv.props.whenChildContentsActiveChanged(false));
             manager.SelectedViewsMap.clear();
diff --git a/src/client/util/ServerStats.tsx b/src/client/util/ServerStats.tsx
index 3c7c35a7e..ac9fecd5c 100644
--- a/src/client/util/ServerStats.tsx
+++ b/src/client/util/ServerStats.tsx
@@ -48,7 +48,7 @@ export class ServerStats extends React.Component<{}> {
                     display: 'flex',
                     height: 300,
                     width: 400,
-                    background: SettingsManager.Instance?.userBackgroundColor,
+                    background: SettingsManager.userBackgroundColor,
                     opacity: 0.6,
                 }}>
                 <div style={{ width: 300, height: 100, margin: 'auto', display: 'flex', flexDirection: 'column' }}>
diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx
index 3ef6c0814..34c752eec 100644
--- a/src/client/views/DashboardView.tsx
+++ b/src/client/views/DashboardView.tsx
@@ -18,7 +18,7 @@ import { CollectionViewType } from '../documents/DocumentTypes';
 import { HistoryUtil } from '../util/History';
 import { ScriptingGlobals } from '../util/ScriptingGlobals';
 import { SharingManager } from '../util/SharingManager';
-import { undoBatch, UndoManager } from '../util/UndoManager';
+import { undoable, undoBatch, UndoManager } from '../util/UndoManager';
 import { CollectionDockingView } from './collections/CollectionDockingView';
 import { CollectionView } from './collections/CollectionView';
 import { ContextMenu } from './ContextMenu';
@@ -270,6 +270,7 @@ export class DashboardView extends React.Component {
     public static openDashboard = (doc: Doc | undefined, fromHistory = false) => {
         if (!doc) return false;
         Doc.AddDocToList(Doc.MyDashboards, 'data', doc);
+        Doc.RemoveDocFromList(Doc.MyRecentlyClosed, 'data', doc);
 
         // this has the side-effect of setting the main container since we're assigning the active/guest dashboard
         Doc.UserDoc() ? (Doc.ActiveDashboard = doc) : (Doc.GuestDashboard = doc);
@@ -307,9 +308,12 @@ export class DashboardView extends React.Component {
     public static removeDashboard = async (dashboard: Doc) => {
         const dashboards = await DocListCastAsync(Doc.MyDashboards.data);
         if (dashboards?.length) {
-            if (dashboard === Doc.ActiveDashboard) DashboardView.openDashboard(dashboards.find(doc => doc !== dashboard));
-            Doc.RemoveDocFromList(Doc.MyDashboards, 'data', dashboard);
-            if (!dashboards.length) Doc.ActivePage = 'home';
+            undoable(() => {
+                if (dashboard === Doc.ActiveDashboard) DashboardView.openDashboard(dashboards.find(doc => doc !== dashboard));
+                Doc.RemoveDocFromList(Doc.MyDashboards, 'data', dashboard);
+                Doc.AddDocToList(Doc.MyRecentlyClosed, 'data', dashboard, undefined, true, true);
+                if (!dashboards.length) Doc.ActivePage = 'home';
+            }, 'remove dashboard')();
         }
     };
 
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index c8b89c1d5..8adb28fe1 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -696,7 +696,7 @@ export class MainView extends React.Component {
         switch (whereFields[0]) {
             case OpenWhere.lightbox:   return LightboxView.AddDocTab(doc, location);
             case OpenWhere.close:      return CollectionDockingView.CloseSplit(doc, whereMods);
-            case OpenWhere.toggle:     return CollectionDockingView.ToggleSplit(doc, whereMods);
+            case OpenWhere.toggle:     return CollectionDockingView.ToggleSplit(doc, whereMods, undefined, "dontSelectOnActivate"); // bcz: hack!  mark the toggle so that it won't be selected on activation- this is needed so that the backlinks menu can toggle views of targets on and off without selecting them
             case OpenWhere.add:default:return CollectionDockingView.AddSplit(doc, whereMods, undefined, undefined, keyValue);
         }
     };
diff --git a/src/client/views/PropertiesDocBacklinksSelector.tsx b/src/client/views/PropertiesDocBacklinksSelector.tsx
index 91a7b3da3..2d1e46361 100644
--- a/src/client/views/PropertiesDocBacklinksSelector.tsx
+++ b/src/client/views/PropertiesDocBacklinksSelector.tsx
@@ -1,3 +1,4 @@
+import { action } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc } from '../../fields/Doc';
@@ -19,16 +20,16 @@ type PropertiesDocBacklinksSelectorProps = {
 
 @observer
 export class PropertiesDocBacklinksSelector extends React.Component<PropertiesDocBacklinksSelectorProps> {
-    getOnClick = (link: Doc) => {
+    getOnClick = action((link: Doc) => {
         const linkAnchor = this.props.Document;
         const other = LinkManager.getOppositeAnchor(link, linkAnchor);
         const otherdoc = !other ? undefined : other.annotationOn && other.type !== DocumentType.RTF ? Cast(other.annotationOn, Doc, null) : other;
-
+        LinkManager.currentLink = link;
         if (otherdoc) {
             otherdoc.hidden = false;
             this.props.addDocTab(Doc.IsDataProto(otherdoc) ? Doc.MakeDelegate(otherdoc) : otherdoc, OpenWhere.toggleRight);
         }
-    };
+    });
 
     render() {
         return !SelectionManager.Views().length ? null : (
diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss
index b116a622c..510defce4 100644
--- a/src/client/views/PropertiesView.scss
+++ b/src/client/views/PropertiesView.scss
@@ -26,6 +26,12 @@
         display: flex;
         flex-direction: row;
     }
+    .propertiesView-titleExtender {
+        text-overflow: ellipsis;
+        max-width: 100%;
+        white-space: pre;
+        overflow: hidden;
+    }
 
     overflow-x: hidden;
     overflow-y: auto;
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 01329b482..6f1461fea 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -3,14 +3,12 @@ import { IconLookup } from '@fortawesome/fontawesome-svg-core';
 import { faAnchor, faArrowRight, faWindowMaximize } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Checkbox, Tooltip } from '@material-ui/core';
-import { Button, Colors, EditableText, IconButton, NumberInput, Size, Slider, Type } from 'browndash-components';
+import { Colors, EditableText, IconButton, NumberInput, Size, Slider, Type } from 'browndash-components';
 import { concat } from 'lodash';
-import { Lambda, action, computed, observable } from 'mobx';
+import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import { ColorState, SketchPicker } from 'react-color';
 import * as Icons from 'react-icons/bs'; //{BsCollectionFill, BsFillFileEarmarkImageFill} from "react-icons/bs"
-import { GrCircleInformation } from 'react-icons/gr';
-import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from '../../Utils';
 import { Doc, DocListCast, Field, FieldResult, HierarchyMapping, NumListCast, Opt, ReverseHierarchyMap, StrListCast } from '../../fields/Doc';
 import { AclAdmin, DocAcl, DocData, Height, Width } from '../../fields/DocSymbols';
 import { Id } from '../../fields/FieldSymbols';
@@ -18,28 +16,29 @@ import { InkField } from '../../fields/InkField';
 import { List } from '../../fields/List';
 import { ComputedField } from '../../fields/ScriptField';
 import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types';
-import { GetEffectiveAcl, SharingPermissions, normalizeEmail } from '../../fields/util';
+import { GetEffectiveAcl, normalizeEmail, SharingPermissions } from '../../fields/util';
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../Utils';
 import { DocumentType } from '../documents/DocumentTypes';
 import { DocumentManager } from '../util/DocumentManager';
 import { GroupManager } from '../util/GroupManager';
 import { LinkManager } from '../util/LinkManager';
 import { SelectionManager } from '../util/SelectionManager';
+import { SettingsManager } from '../util/SettingsManager';
 import { SharingManager } from '../util/SharingManager';
 import { Transform } from '../util/Transform';
-import { UndoManager, undoBatch, undoable } from '../util/UndoManager';
+import { undoable, undoBatch, UndoManager } from '../util/UndoManager';
 import { EditableView } from './EditableView';
 import { FilterPanel } from './FilterPanel';
 import { InkStrokeProperties } from './InkStrokeProperties';
+import { DocumentView, OpenWhere, StyleProviderFunc } from './nodes/DocumentView';
+import { KeyValueBox } from './nodes/KeyValueBox';
+import { PresBox, PresEffect, PresEffectDirection } from './nodes/trails';
 import { PropertiesButtons } from './PropertiesButtons';
 import { PropertiesDocBacklinksSelector } from './PropertiesDocBacklinksSelector';
 import { PropertiesDocContextSelector } from './PropertiesDocContextSelector';
 import { PropertiesSection } from './PropertiesSection';
 import './PropertiesView.scss';
 import { DefaultStyleProvider } from './StyleProvider';
-import { DocumentView, OpenWhere, StyleProviderFunc } from './nodes/DocumentView';
-import { KeyValueBox } from './nodes/KeyValueBox';
-import { PresBox, PresEffect, PresEffectDirection } from './nodes/trails';
-import { SettingsManager } from '../util/SettingsManager';
 const _global = (window /* browser */ || global) /* node */ as any;
 
 interface PropertiesViewProps {
@@ -87,13 +86,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @observable openTransform: boolean = true;
     @observable openFilters: boolean = false;
 
-    /**
-     * autorun to set up the filter doc of a collection if that collection has been selected and the filters panel is open
-     */
-    private selectedDocListenerDisposer: Opt<Lambda>;
-
-    // @observable selectedUser: string = "";
-    // @observable addButtonPressed: boolean = false;
     @observable layoutDocAcls: boolean = false;
 
     //Pres Trails booleans:
@@ -105,14 +97,21 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     @observable inOptions: boolean = false;
     @observable _controlButton: boolean = false;
+    private _disposers: { [name: string]: IReactionDisposer } = {};
 
     componentDidMount() {
-        this.selectedDocListenerDisposer?.();
-        // this.selectedDocListenerDisposer = autorun(() => this.openFilters && this.selectedDoc && this.checkFilterDoc());
+        this._disposers.link = reaction(
+            () => LinkManager.currentLink,
+            link => {
+                link && this.onDoubleClick();
+                link && (this.openLinks = true);
+            },
+            { fireImmediately: true }
+        );
     }
 
     componentWillUnmount() {
-        this.selectedDocListenerDisposer?.();
+        Object.values(this._disposers).forEach(disposer => disposer?.());
     }
 
     @computed get isInk() {
@@ -555,9 +554,29 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     @computed get editableTitle() {
         const titles = new Set<string>();
-        const title = Array.from(titles.keys()).length > 1 ? '--multiple selected--' : StrCast(this.selectedDoc?.title);
         SelectionManager.Views().forEach(dv => titles.add(StrCast(dv.rootDoc.title)));
-        return <EditableText val={title} setVal={this.setTitle} color={this.color} type={Type.SEC} formLabel={'Title'} fillWidth />;
+        const title = Array.from(titles.keys()).length > 1 ? '--multiple selected--' : StrCast(this.selectedDoc?.title);
+        return (
+            <div>
+                <EditableText val={title} setVal={this.setTitle} color={this.color} type={Type.SEC} formLabel={'Title'} fillWidth />
+                {LinkManager.currentLinkAnchor ? (
+                    <p className="propertiesView-titleExtender">
+                        <>
+                            <b>Anchor:</b>
+                            {LinkManager.currentLinkAnchor.title}
+                        </>
+                    </p>
+                ) : null}
+                {LinkManager.currentLink?.title ? (
+                    <p className="propertiesView-titleExtender">
+                        <>
+                            <b>Link:</b>
+                            {LinkManager.currentLink.title}
+                        </>
+                    </p>
+                ) : null}
+            </div>
+        );
     }
 
     @computed get currentType() {
@@ -1101,7 +1120,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 isOpen={this.openOptions}
                 setInSection={bool => (this.inOptions = bool)}
                 setIsOpen={bool => (this.openOptions = bool)}
-                onDoubleClick={() => this.onDoubleClick()}
+                onDoubleClick={this.onDoubleClick}
             />
         );
     }
@@ -1209,11 +1228,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     @computed get linksSubMenu() {
-        return <PropertiesSection title="Linked To" content={this.linkCount > 0 ? this.links : 'There are no current links.'} isOpen={this.openLinks} setIsOpen={bool => (this.openLinks = bool)} onDoubleClick={() => this.onDoubleClick()} />;
+        return <PropertiesSection title="Linked To" content={this.linkCount > 0 ? this.links : 'There are no current links.'} isOpen={this.openLinks} setIsOpen={bool => (this.openLinks = bool)} onDoubleClick={this.onDoubleClick} />;
     }
 
     @computed get layoutSubMenu() {
-        return <PropertiesSection title="Layout" content={this.layoutPreview} isOpen={this.openLayout} setIsOpen={bool => (this.openLayout = bool)} onDoubleClick={() => this.onDoubleClick()} />;
+        return <PropertiesSection title="Layout" content={this.layoutPreview} isOpen={this.openLayout} setIsOpen={bool => (this.openLayout = bool)} onDoubleClick={this.onDoubleClick} />;
     }
 
     @computed get description() {
@@ -1699,7 +1718,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                         <div className="propertiesView-type"> {this.currentType} </div>
                         {this.optionsSubMenu}
                         {this.linksSubMenu}
-                        {!this.selectedDoc || !LinkManager.currentLink || (!hasSelectedAnchor && this.selectedDoc !== LinkManager.currentLink) ? null : this.linkProperties}
+                        {!LinkManager.currentLink || !this.openLinks ? null : this.linkProperties}
                         {this.inkSubMenu}
                         {this.contextsSubMenu}
                         {this.fieldsSubMenu}
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 6cdb84dea..9823dfe91 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -348,7 +348,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     private onActiveContentItemChanged(contentItem: any) {
         if (!contentItem || (this.stack === contentItem.parent && ((contentItem?.tab === this.tab && !this._isActive) || (contentItem?.tab !== this.tab && this._isActive)))) {
             this._activated = this._isActive = !contentItem || contentItem?.tab === this.tab;
-            if (!this._view) setTimeout(() => SelectionManager.SelectView(this._view, false));
+            if (!this._view && this.tab?.contentItem?.config?.props?.panelName !== 'dontSelectOnActivate') setTimeout(() => SelectionManager.SelectView(this._view, false));
             !this._isActive && this._document && Doc.UnBrushDoc(this._document); // bcz: bad -- trying to simulate a pointer leave event when a new tab is opened up on top of an existing one.
         }
     }
@@ -380,7 +380,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                                        return LightboxView.AddDocTab(doc, location);
             case OpenWhere.close:      return CollectionDockingView.CloseSplit(doc, whereMods);
             case OpenWhere.replace:    return CollectionDockingView.ReplaceTab(doc, whereMods, this.stack, undefined, keyValue);
-            case OpenWhere.toggle:     return CollectionDockingView.ToggleSplit(doc, whereMods, this.stack, undefined, keyValue);
+            case OpenWhere.toggle:     return CollectionDockingView.ToggleSplit(doc, whereMods, this.stack, "dontSelectOnActivate", keyValue);
             case OpenWhere.add:default:return CollectionDockingView.AddSplit(doc, whereMods, this.stack, undefined, keyValue);
         }
     };
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 9bc8f5e8b..0a9d7543b 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -69,10 +69,8 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
         }
         return this.props.sourceDoc;
     }
-    @action
+
     onEdit = (e: React.PointerEvent) => {
-        LinkManager.currentLink = this.props.linkDoc === LinkManager.currentLink ? undefined : this.props.linkDoc;
-        LinkManager.currentLinkAnchor = this.sourceAnchor;
         setupMoveUpEvents(
             this,
             e,
@@ -90,8 +88,11 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                     DocumentViewInternal.addDocTabFunc(trail, OpenWhere.replaceRight);
                 } else {
                     SelectionManager.SelectView(this.props.docView, false);
+                    LinkManager.currentLink = this.props.linkDoc === LinkManager.currentLink ? undefined : this.props.linkDoc;
+                    LinkManager.currentLinkAnchor = LinkManager.currentLink ? this.sourceAnchor : undefined;
+
                     if ((SettingsManager.propertiesWidth ?? 0) < 100) {
-                        SettingsManager.propertiesWidth = 250;
+                        setTimeout(action(() => (SettingsManager.propertiesWidth = 250)));
                     }
                 }
             })
@@ -150,7 +151,11 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                 className="linkMenu-item"
                 onPointerEnter={action(e => (this._hover = true))}
                 onPointerLeave={action(e => (this._hover = false))}
-                style={{ background: /*LinkManager.currentLink !== this.props.linkDoc*/ this._hover ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}>
+                style={{
+                    fontSize: this._hover ? 'larger' : undefined,
+                    fontWeight: this._hover ? 'bold' : undefined,
+                    background: LinkManager.currentLink === this.props.linkDoc ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
+                }}>
                 <div className="linkMenu-item-content expand-two">
                     <div
                         ref={this._drag}
-- 
cgit v1.2.3-70-g09d2


From 888ddd78737781f8a2d045b5f1e41788c512c94d Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 8 Sep 2023 17:02:49 -0400
Subject: don't remove current recording from overlay, added closeOnSelect
 option  for dropdown.   place recording box on screen.  fixe overlayView to
 keep views on screen. fixed schema view checkboxes. don't cause tab to
 rerender when colelctoin type changes.  add dropdown to filter indicator to
 find filters.

---
 package-lock.json                                  | 166 +++++++++++++--------
 package.json                                       |   2 +-
 src/client/util/CurrentUserUtils.ts                |   1 -
 src/client/util/SettingsManager.tsx                |   6 +-
 src/client/util/reportManager/ReportManager.tsx    |   2 +
 src/client/views/DashboardView.tsx                 |   1 +
 src/client/views/MainView.tsx                      |   6 +-
 src/client/views/OverlayView.tsx                   |  15 ++
 src/client/views/PropertiesButtons.tsx             |   1 +
 src/client/views/PropertiesView.tsx                |  39 +++--
 src/client/views/StyleProvider.scss                |   9 +-
 src/client/views/StyleProvider.tsx                 |  41 ++++-
 src/client/views/UndoStack.tsx                     |  12 +-
 src/client/views/collections/TabDocView.tsx        |  10 +-
 .../collectionSchema/CollectionSchemaView.tsx      |   8 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |   3 +-
 .../views/nodes/RecordingBox/RecordingBox.tsx      |   9 +-
 17 files changed, 213 insertions(+), 118 deletions(-)

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

diff --git a/package-lock.json b/package-lock.json
index b6c03c6ba..6055e9d1e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -142,20 +142,20 @@
             "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ=="
         },
         "@babel/core": {
-            "version": "7.22.15",
-            "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.15.tgz",
-            "integrity": "sha512-PtZqMmgRrvj8ruoEOIwVA3yoF91O+Hgw9o7DAUTNBA6Mo2jpu31clx9a7Nz/9JznqetTR6zwfC4L3LAjKQXUwA==",
+            "version": "7.22.17",
+            "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.17.tgz",
+            "integrity": "sha512-2EENLmhpwplDux5PSsZnSbnSkB3tZ6QTksgO25xwEL7pIDcNOMhF5v/s6RzwjMZzZzw9Ofc30gHv5ChCC8pifQ==",
             "requires": {
                 "@ampproject/remapping": "^2.2.0",
                 "@babel/code-frame": "^7.22.13",
                 "@babel/generator": "^7.22.15",
                 "@babel/helper-compilation-targets": "^7.22.15",
-                "@babel/helper-module-transforms": "^7.22.15",
+                "@babel/helper-module-transforms": "^7.22.17",
                 "@babel/helpers": "^7.22.15",
-                "@babel/parser": "^7.22.15",
+                "@babel/parser": "^7.22.16",
                 "@babel/template": "^7.22.15",
-                "@babel/traverse": "^7.22.15",
-                "@babel/types": "^7.22.15",
+                "@babel/traverse": "^7.22.17",
+                "@babel/types": "^7.22.17",
                 "convert-source-map": "^1.7.0",
                 "debug": "^4.1.0",
                 "gensync": "^1.0.0-beta.2",
@@ -209,9 +209,9 @@
                     }
                 },
                 "@babel/traverse": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.15.tgz",
-                    "integrity": "sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.17.tgz",
+                    "integrity": "sha512-xK4Uwm0JnAMvxYZxOVecss85WxTEIbTa7bnGyf/+EgCL5Zt3U7htUpEOWv9detPlamGKuRzCqw74xVglDWpPdg==",
                     "requires": {
                         "@babel/code-frame": "^7.22.13",
                         "@babel/generator": "^7.22.15",
@@ -219,16 +219,16 @@
                         "@babel/helper-function-name": "^7.22.5",
                         "@babel/helper-hoist-variables": "^7.22.5",
                         "@babel/helper-split-export-declaration": "^7.22.6",
-                        "@babel/parser": "^7.22.15",
-                        "@babel/types": "^7.22.15",
+                        "@babel/parser": "^7.22.16",
+                        "@babel/types": "^7.22.17",
                         "debug": "^4.1.0",
                         "globals": "^11.1.0"
                     }
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -300,9 +300,9 @@
                     "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -472,9 +472,9 @@
                     "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -492,9 +492,9 @@
             }
         },
         "@babel/helper-module-transforms": {
-            "version": "7.22.15",
-            "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.15.tgz",
-            "integrity": "sha512-l1UiX4UyHSFsYt17iQ3Se5pQQZZHa22zyIXURmvkmLCD4t/aU+dvNWHatKac/D9Vm9UES7nvIqHs4jZqKviUmQ==",
+            "version": "7.22.17",
+            "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.17.tgz",
+            "integrity": "sha512-XouDDhQESrLHTpnBtCKExJdyY4gJCdrvH2Pyv8r8kovX2U8G0dRUOT45T9XlbLtuu9CLXP15eusnkprhoPV5iQ==",
             "requires": {
                 "@babel/helper-environment-visitor": "^7.22.5",
                 "@babel/helper-module-imports": "^7.22.15",
@@ -517,9 +517,9 @@
                     "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -542,13 +542,13 @@
             "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ=="
         },
         "@babel/helper-remap-async-to-generator": {
-            "version": "7.22.9",
-            "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz",
-            "integrity": "sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==",
+            "version": "7.22.17",
+            "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.17.tgz",
+            "integrity": "sha512-bxH77R5gjH3Nkde6/LuncQoLaP16THYPscurp1S8z7S9ZgezCyV3G8Hc+TZiCmY8pz4fp8CvKSgtJMW0FkLAxA==",
             "requires": {
                 "@babel/helper-annotate-as-pure": "^7.22.5",
                 "@babel/helper-environment-visitor": "^7.22.5",
-                "@babel/helper-wrap-function": "^7.22.9"
+                "@babel/helper-wrap-function": "^7.22.17"
             },
             "dependencies": {
                 "@babel/helper-annotate-as-pure": {
@@ -611,28 +611,64 @@
             "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA=="
         },
         "@babel/helper-wrap-function": {
-            "version": "7.22.10",
-            "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz",
-            "integrity": "sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ==",
+            "version": "7.22.17",
+            "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.17.tgz",
+            "integrity": "sha512-nAhoheCMlrqU41tAojw9GpVEKDlTS8r3lzFmF0lP52LwblCPbuFSO7nGIZoIcoU5NIm1ABrna0cJExE4Ay6l2Q==",
             "requires": {
                 "@babel/helper-function-name": "^7.22.5",
-                "@babel/template": "^7.22.5",
-                "@babel/types": "^7.22.10"
+                "@babel/template": "^7.22.15",
+                "@babel/types": "^7.22.17"
             },
             "dependencies": {
-                "@babel/helper-validator-identifier": {
+                "@babel/code-frame": {
+                    "version": "7.22.13",
+                    "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+                    "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
+                    "requires": {
+                        "@babel/highlight": "^7.22.13",
+                        "chalk": "^2.4.2"
+                    }
+                },
+                "@babel/highlight": {
+                    "version": "7.22.13",
+                    "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
+                    "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
+                    "requires": {
+                        "@babel/helper-validator-identifier": "^7.22.5",
+                        "chalk": "^2.4.2",
+                        "js-tokens": "^4.0.0"
+                    }
+                },
+                "@babel/parser": {
+                    "version": "7.22.16",
+                    "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
+                    "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA=="
+                },
+                "@babel/template": {
                     "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
-                    "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+                    "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+                    "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+                    "requires": {
+                        "@babel/code-frame": "^7.22.13",
+                        "@babel/parser": "^7.22.15",
+                        "@babel/types": "^7.22.15"
+                    }
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
                         "to-fast-properties": "^2.0.0"
+                    },
+                    "dependencies": {
+                        "@babel/helper-validator-identifier": {
+                            "version": "7.22.15",
+                            "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+                            "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+                        }
                     }
                 }
             }
@@ -693,9 +729,9 @@
                     }
                 },
                 "@babel/traverse": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.15.tgz",
-                    "integrity": "sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.17.tgz",
+                    "integrity": "sha512-xK4Uwm0JnAMvxYZxOVecss85WxTEIbTa7bnGyf/+EgCL5Zt3U7htUpEOWv9detPlamGKuRzCqw74xVglDWpPdg==",
                     "requires": {
                         "@babel/code-frame": "^7.22.13",
                         "@babel/generator": "^7.22.15",
@@ -703,16 +739,16 @@
                         "@babel/helper-function-name": "^7.22.5",
                         "@babel/helper-hoist-variables": "^7.22.5",
                         "@babel/helper-split-export-declaration": "^7.22.6",
-                        "@babel/parser": "^7.22.15",
-                        "@babel/types": "^7.22.15",
+                        "@babel/parser": "^7.22.16",
+                        "@babel/types": "^7.22.17",
                         "debug": "^4.1.0",
                         "globals": "^11.1.0"
                     }
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -1691,9 +1727,9 @@
                     }
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -2028,9 +2064,9 @@
                     "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -6651,9 +6687,9 @@
             }
         },
         "browndash-components": {
-            "version": "0.1.23",
-            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.1.23.tgz",
-            "integrity": "sha512-yZPnSUBXdToufaq4mTYHMgDwrijQWsuVKK8j+NilRKMqmOrkZeqyRhncTDz077DcMLcjeIj+SobT3GPK04TXmQ==",
+            "version": "0.1.25",
+            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.1.25.tgz",
+            "integrity": "sha512-YgzUsfeUKwtaOLRYNDcxybZG2Ip7KSQV38VbUrgC+ycwOX/tzq9IWlfw2z4h/EVuVcq+ERCaBS4pb3mMU6pKGQ==",
             "requires": {
                 "@emotion/react": "^11.11.1",
                 "@emotion/styled": "^11.11.0",
@@ -10110,14 +10146,14 @@
                     }
                 },
                 "caniuse-lite": {
-                    "version": "1.0.30001528",
-                    "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001528.tgz",
-                    "integrity": "sha512-0Db4yyjR9QMNlsxh+kKWzQtkyflkG/snYheSzkjmvdEtEXB1+jt7A2HmSEiO6XIJPIbo92lHNGNySvE5pZcs5Q=="
+                    "version": "1.0.30001529",
+                    "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001529.tgz",
+                    "integrity": "sha512-n2pUQYGAkrLG4QYj2desAh+NqsJpHbNmVZz87imptDdxLAtjxary7Df/psdfyDGmskJK/9Dt9cPnx5RZ3CU4Og=="
                 },
                 "electron-to-chromium": {
-                    "version": "1.4.510",
-                    "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.510.tgz",
-                    "integrity": "sha512-xPfLIPFcN/WLXBpQ/K4UgE98oUBO5Tia6BD4rkSR0wE7ep/PwBVlgvPJQrIBpmJGVAmUzwPKuDbVt9XV6+uC2g=="
+                    "version": "1.4.513",
+                    "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.513.tgz",
+                    "integrity": "sha512-cOB0xcInjm+E5qIssHeXJ29BaUyWpMyFKT5RB3bsLENDheCja0wMkHJyiPl0NBE/VzDI7JDuNEQWhe6RitEUcw=="
                 }
             }
         },
diff --git a/package.json b/package.json
index c218d80ff..9f0b91628 100644
--- a/package.json
+++ b/package.json
@@ -178,7 +178,7 @@
         "body-parser": "^1.19.2",
         "bootstrap": "^4.6.1",
         "brotli": "^1.3.3",
-        "browndash-components": "^0.1.23",
+        "browndash-components": "^0.1.25",
         "browser-assert": "^1.2.1",
         "bson": "^4.6.1",
         "canvas": "^2.9.3",
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index aa5f2658a..8bedea562 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -763,7 +763,6 @@ export class CurrentUserUtils {
     }
     /// Initializes all the default buttons for the top bar context menu
     static setupTopbarButtons(doc: Doc, field="myTopBarBtns") {
-        if (Doc.UserDoc().currentRecording) Doc.RemFromMyOverlay(DocCast(Doc.UserDoc().currentRecording));
         Doc.UserDoc().currentRecording = undefined;
         Doc.UserDoc().workspaceRecordingState = undefined;
         Doc.UserDoc().workspaceReplayingState = undefined;
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index 720badd40..53cfbc947 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -142,6 +142,7 @@ export class SettingsManager extends React.Component<{}> {
                     formLabel="Theme"
                     size={Size.SMALL}
                     type={Type.TERT}
+                    closeOnSelect={false}
                     selectedVal={userTheme}
                     setSelectedVal={scheme => this.changeColorScheme(scheme as string)}
                     items={colorSchemes.map((scheme, i) => ({
@@ -294,6 +295,7 @@ export class SettingsManager extends React.Component<{}> {
                                         },
                                     };
                                 })}
+                                closeOnSelect={true}
                                 dropdownType={DropdownType.SELECT}
                                 type={Type.TERT}
                                 selectedVal={StrCast(Doc.UserDoc().fontFamily)}
@@ -373,6 +375,7 @@ export class SettingsManager extends React.Component<{}> {
                     <div className="tab-column-content">
                         <Dropdown
                             formLabel={'Mode'}
+                            closeOnSelect={true}
                             items={[
                                 {
                                     text: 'Novice',
@@ -403,7 +406,8 @@ export class SettingsManager extends React.Component<{}> {
                     </div>
                     <div className="tab-column-content">
                         <Dropdown
-                            formLabel={'Scroll Mode'}
+                            formLabel="Scroll Mode"
+                            closeOnSelect={true}
                             items={[
                                 {
                                     text: 'Scroll to Pan',
diff --git a/src/client/util/reportManager/ReportManager.tsx b/src/client/util/reportManager/ReportManager.tsx
index 6a236face..08467448d 100644
--- a/src/client/util/reportManager/ReportManager.tsx
+++ b/src/client/util/reportManager/ReportManager.tsx
@@ -308,6 +308,7 @@ export class ReportManager extends React.Component<{}> {
                     <Dropdown
                         color={StrCast(Doc.UserDoc().userColor)}
                         formLabel={'Type'}
+                        closeOnSelect={true}
                         items={bugDropdownItems}
                         selectedVal={this.formData.type}
                         setSelectedVal={val => {
@@ -320,6 +321,7 @@ export class ReportManager extends React.Component<{}> {
                     <Dropdown
                         color={StrCast(Doc.UserDoc().userColor)}
                         formLabel={'Priority'}
+                        closeOnSelect={true}
                         items={priorityDropdownItems}
                         selectedVal={this.formData.priority}
                         setSelectedVal={val => {
diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx
index 1d1d0eaab..014a6358f 100644
--- a/src/client/views/DashboardView.tsx
+++ b/src/client/views/DashboardView.tsx
@@ -371,6 +371,7 @@ export class DashboardView extends React.Component {
 
         Doc.AddDocToList(Doc.MyHeaderBar, 'data', freeformDoc);
         dashboardDoc['pane-count'] = 1;
+        freeformDoc.embedContainer = dashboardDoc;
 
         Doc.AddDocToList(Doc.MyDashboards, 'data', dashboardDoc);
 
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 8adb28fe1..2b4f4d5f7 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -810,7 +810,11 @@ export class MainView extends React.Component {
                             </div>
                         )}
                         <div className="properties-container" style={{ width: this.propertiesWidth(), color: SettingsManager.userColor }}>
-                            {this.propertiesWidth() < 10 ? null : <PropertiesView styleProvider={DefaultStyleProvider} addDocTab={DocumentViewInternal.addDocTabFunc} width={this.propertiesWidth()} height={this.propertiesHeight()} />}
+                            {
+                                <div style={{ display: this.propertiesWidth() < 10 ? 'none' : undefined }}>
+                                    <PropertiesView styleProvider={DefaultStyleProvider} addDocTab={DocumentViewInternal.addDocTabFunc} width={this.propertiesWidth()} height={this.propertiesHeight()} />
+                                </div>
+                            }
                         </div>
                     </div>
                 </div>
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 5d95c5fda..c174befc0 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -16,6 +16,7 @@ import { LightboxView } from './LightboxView';
 import { DocumentView, DocumentViewInternal } from './nodes/DocumentView';
 import './OverlayView.scss';
 import { DefaultStyleProvider } from './StyleProvider';
+const _global = (window /* browser */ || global) /* node */ as any;
 
 export type OverlayDisposer = () => void;
 
@@ -115,6 +116,20 @@ export class OverlayView extends React.Component {
         super(props);
         if (!OverlayView.Instance) {
             OverlayView.Instance = this;
+            new _global.ResizeObserver(
+                action((entries: any) => {
+                    for (const entry of entries) {
+                        DocListCast(Doc.MyOverlayDocs?.data).forEach(doc => {
+                            if (NumCast(doc.overlayX) > entry.contentRect.width - 10) {
+                                doc.overlayX = entry.contentRect.width - 10;
+                            }
+                            if (NumCast(doc.overlayY) > entry.contentRect.height - 10) {
+                                doc.overlayY = entry.contentRect.height - 10;
+                            }
+                        });
+                    }
+                })
+            ).observe(window.document.body);
         }
     }
 
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 42db0b9be..d939470e9 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -376,6 +376,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             <Dropdown
                 tooltip={'Choose onClick behavior'}
                 items={items}
+                closeOnSelect={true}
                 selectedVal={this.onClickVal}
                 setSelectedVal={val => this.handleOptionChange(val as string)}
                 title={'Choose onClick behaviour'}
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 72ff906f6..9cc75b1c6 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -52,6 +52,12 @@ interface PropertiesViewProps {
 export class PropertiesView extends React.Component<PropertiesViewProps> {
     private _widthUndo?: UndoManager.Batch;
 
+    public static Instance: PropertiesView | undefined;
+    constructor(props: any) {
+        super(props);
+        PropertiesView.Instance = this;
+    }
+
     @computed get MAX_EMBED_HEIGHT() {
         return 200;
     }
@@ -75,6 +81,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     @observable layoutFields: boolean = false;
+    @observable layoutDocAcls: boolean = false;
 
     @observable openOptions: boolean = true;
     @observable openSharing: boolean = true;
@@ -86,8 +93,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @observable openTransform: boolean = true;
     @observable openFilters: boolean = false;
 
-    @observable layoutDocAcls: boolean = false;
-
     //Pres Trails booleans:
     @observable openPresTransitions: boolean = true;
     @observable openPresProgressivize: boolean = false;
@@ -103,7 +108,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         this._disposers.link = reaction(
             () => LinkManager.currentLink,
             link => {
-                link && this.onDoubleClick();
+                link && this.CloseAll();
                 link && (this.openLinks = true);
             },
             { fireImmediately: true }
@@ -970,7 +975,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     };
 
     @action
-    onDoubleClick = () => {
+    CloseAll = () => {
         this.openContexts = false;
         this.openLinks = false;
         this.openOptions = false;
@@ -1120,7 +1125,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 isOpen={this.openOptions}
                 setInSection={bool => (this.inOptions = bool)}
                 setIsOpen={bool => (this.openOptions = bool)}
-                onDoubleClick={this.onDoubleClick}
+                onDoubleClick={this.CloseAll}
             />
         );
     }
@@ -1147,7 +1152,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 }
                 isOpen={this.openSharing}
                 setIsOpen={bool => (this.openSharing = bool)}
-                onDoubleClick={() => this.onDoubleClick()}
+                onDoubleClick={() => this.CloseAll()}
             />
         );
     }
@@ -1187,7 +1192,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 }
                 isOpen={this.openFilters}
                 setIsOpen={bool => (this.openFilters = bool)}
-                onDoubleClick={() => this.onDoubleClick()}
+                onDoubleClick={() => this.CloseAll()}
             />
         );
     }
@@ -1197,8 +1202,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
         return (
             <>
-                <PropertiesSection title="Appearance" content={this.isInk ? this.appearanceEditor : null} isOpen={this.openAppearance} setIsOpen={bool => (this.openAppearance = bool)} onDoubleClick={() => this.onDoubleClick()} />
-                <PropertiesSection title="Transform" content={this.transformEditor} isOpen={this.openTransform} setIsOpen={bool => (this.openTransform = bool)} onDoubleClick={() => this.onDoubleClick()} />
+                <PropertiesSection title="Appearance" content={this.isInk ? this.appearanceEditor : null} isOpen={this.openAppearance} setIsOpen={bool => (this.openAppearance = bool)} onDoubleClick={() => this.CloseAll()} />
+                <PropertiesSection title="Transform" content={this.transformEditor} isOpen={this.openTransform} setIsOpen={bool => (this.openTransform = bool)} onDoubleClick={() => this.CloseAll()} />
             </>
         );
     }
@@ -1210,29 +1215,23 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 content={<div className="propertiesView-content fields">{Doc.noviceMode ? this.noviceFields : this.expandedField}</div>}
                 isOpen={this.openFields}
                 setIsOpen={bool => (this.openFields = bool)}
-                onDoubleClick={() => this.onDoubleClick()}
+                onDoubleClick={() => this.CloseAll()}
             />
         );
     }
 
     @computed get contextsSubMenu() {
         return (
-            <PropertiesSection
-                title="Other Contexts"
-                content={this.contextCount > 0 ? this.contexts : 'There are no other contexts.'}
-                isOpen={this.openContexts}
-                setIsOpen={bool => (this.openContexts = bool)}
-                onDoubleClick={() => this.onDoubleClick()}
-            />
+            <PropertiesSection title="Other Contexts" content={this.contextCount > 0 ? this.contexts : 'There are no other contexts.'} isOpen={this.openContexts} setIsOpen={bool => (this.openContexts = bool)} onDoubleClick={() => this.CloseAll()} />
         );
     }
 
     @computed get linksSubMenu() {
-        return <PropertiesSection title="Linked To" content={this.linkCount > 0 ? this.links : 'There are no current links.'} isOpen={this.openLinks} setIsOpen={bool => (this.openLinks = bool)} onDoubleClick={this.onDoubleClick} />;
+        return <PropertiesSection title="Linked To" content={this.linkCount > 0 ? this.links : 'There are no current links.'} isOpen={this.openLinks} setIsOpen={bool => (this.openLinks = bool)} onDoubleClick={this.CloseAll} />;
     }
 
     @computed get layoutSubMenu() {
-        return <PropertiesSection title="Layout" content={this.layoutPreview} isOpen={this.openLayout} setIsOpen={bool => (this.openLayout = bool)} onDoubleClick={this.onDoubleClick} />;
+        return <PropertiesSection title="Layout" content={this.layoutPreview} isOpen={this.openLayout} setIsOpen={bool => (this.openLayout = bool)} onDoubleClick={this.CloseAll} />;
     }
 
     @computed get description() {
@@ -1723,7 +1722,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                         {this.contextsSubMenu}
                         {this.fieldsSubMenu}
                         {isNovice ? null : this.sharingSubMenu}
-                        {isNovice ? null : this.filtersSubMenu}
+                        {this.filtersSubMenu}
                         {isNovice ? null : this.layoutSubMenu}
                     </div>
                 );
diff --git a/src/client/views/StyleProvider.scss b/src/client/views/StyleProvider.scss
index c06bb287e..f069e7e1b 100644
--- a/src/client/views/StyleProvider.scss
+++ b/src/client/views/StyleProvider.scss
@@ -18,10 +18,15 @@
     cursor: default;
 }
 .styleProvider-filter {
-    right: 0;
+    right: 15;
+    .styleProvider-filterShift {
+        left: 0;
+        top: 0;
+        position: absolute;
+    }
 }
 .styleProvider-audio {
-    right: 15;
+    right: 30;
 }
 .styleProvider-lock:hover,
 .styleProvider-audio:hover,
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 069bfd049..8a5ad3139 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -1,7 +1,7 @@
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Tooltip } from '@material-ui/core';
-import { IconButton, Shadows, Size } from 'browndash-components';
+import { Dropdown, DropdownType, IconButton, IListItemProps, ListBox, ListItem, Popup, Shadows, Size, Type } from 'browndash-components';
 import { action, runInAction } from 'mobx';
 import { extname } from 'path';
 import { BsArrowDown, BsArrowDownUp, BsArrowUp } from 'react-icons/bs';
@@ -24,6 +24,8 @@ import { KeyValueBox } from './nodes/KeyValueBox';
 import { SliderBox } from './nodes/SliderBox';
 import './StyleProvider.scss';
 import React = require('react');
+import { PropertiesView } from './PropertiesView';
+import { FaFilter } from 'react-icons/fa';
 
 export enum StyleProp {
     TreeViewIcon = 'treeView_Icon',
@@ -283,13 +285,44 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             const filter = () => {
                 const showFilterIcon =
                     StrListCast(doc?._childFilters).length || StrListCast(doc?._childFiltersByRanges).length
-                        ? '#18c718bd' //'hasFilter'
+                        ? 'green' // #18c718bd' //'hasFilter'
                         : docProps?.childFilters?.().filter(f => Utils.IsRecursiveFilter(f) && f !== Utils.noDragsDocFilter).length || docProps?.childFiltersByRanges().length
                         ? 'orange' //'inheritsFilter'
                         : undefined;
                 return !showFilterIcon ? null : (
-                    <div className="styleProvider-filter" onClick={action(() => (SettingsManager.propertiesWidth = 250))}>
-                        <FontAwesomeIcon icon={'filter'} size="lg" style={{ position: 'absolute', top: '1%', right: '1%', cursor: 'pointer', padding: 1, color: showFilterIcon, zIndex: 1 }} />
+                    <div className="styleProvider-filter">
+                        <Dropdown
+                            type={Type.TERT}
+                            dropdownType={DropdownType.CLICK}
+                            fillWidth
+                            iconProvider={(active:boolean) => <div className='styleProvider-filterShift'><FaFilter/></div>}
+                            closeOnSelect={true}
+                            setSelectedVal={
+                                action((dv) => {
+                                    (dv as any).select(false);
+                                    (SettingsManager.propertiesWidth = 250);
+                                    setTimeout(action(() => {
+                                        if (PropertiesView.Instance) {
+                                            PropertiesView.Instance.CloseAll();
+                                            PropertiesView.Instance.openFilters = true;
+                                        }
+                                    }));
+                                })
+                            }
+                            size={Size.XSMALL}
+                            width={15}
+                            height={15}
+                            title={showFilterIcon === 'green' ? 
+                                "This view is filtered.  Click to view/change filters":
+                                "this view inherits filters from one of its parents"}
+                            color={SettingsManager.userColor}
+                            background={showFilterIcon}
+                            items={[...(props?.docViewPath?.()??[]), ...(props?.DocumentView?[props?.DocumentView?.()]:[])].map(dv => ({
+                                text: StrCast(dv.rootDoc.title),
+                                val: dv as any,
+                                style: {color:SettingsManager.userColor, background:SettingsManager.userBackgroundColor},
+                            } as IListItemProps)) }
+                        />
                     </div>
                 );
             };
diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx
index 1afd5ad22..093bb8b9c 100644
--- a/src/client/views/UndoStack.tsx
+++ b/src/client/views/UndoStack.tsx
@@ -1,14 +1,12 @@
-import { action, observable } from 'mobx';
+import { Tooltip } from '@mui/material';
+import { Popup, Type } from 'browndash-components';
+import { observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { UndoManager } from '../util/UndoManager';
-import './UndoStack.scss';
 import { StrCast } from '../../fields/Types';
-import { Doc } from '../../fields/Doc';
-import { Popup, Type, isDark } from 'browndash-components';
-import { Colors } from './global/globalEnums';
 import { SettingsManager } from '../util/SettingsManager';
-import { Tooltip } from '@mui/material';
+import { UndoManager } from '../util/UndoManager';
+import './UndoStack.scss';
 
 interface UndoStackProps {
     width?: number;
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 9ea1ed2de..d9faab063 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -17,6 +17,7 @@ import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'
 import { DocumentManager } from '../../util/DocumentManager';
 import { DragManager, dropActionType } from '../../util/DragManager';
 import { SelectionManager } from '../../util/SelectionManager';
+import { SettingsManager } from '../../util/SettingsManager';
 import { SnappingManager } from '../../util/SnappingManager';
 import { Transform } from '../../util/Transform';
 import { undoable, UndoManager } from '../../util/UndoManager';
@@ -33,7 +34,6 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV
 import { CollectionView } from './CollectionView';
 import './TabDocView.scss';
 import React = require('react');
-import { SettingsManager } from '../../util/SettingsManager';
 const _global = (window /* browser */ || global) /* node */ as any;
 
 interface TabDocViewProps {
@@ -420,7 +420,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     PanelHeight = () => this._panelHeight;
     miniMapColor = () => Colors.MEDIUM_GRAY;
     tabView = () => this._view;
-    disableMinimap = () => !this._document || this._document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._document)) || this._document?._type_collection !== CollectionViewType.Freeform;
+    disableMinimap = () => !this._document;
     whenChildContentActiveChanges = (isActive: boolean) => (this._isAnyChildContentActive = isActive);
     isContentActive = () => this._isContentActive;
     waitForDoubleClick = () => (DocumentView.ExploreMode ? 'never' : undefined);
@@ -461,9 +461,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                     bringToFront={emptyFunction}
                     pinToPres={TabDocView.PinDoc}
                 />
-                {this.disableMinimap() || this._document._type_collection !== CollectionViewType.Freeform ? null : (
-                    <TabMinimapView key="minimap" addDocTab={this.addDocTab} PanelHeight={this.PanelHeight} PanelWidth={this.PanelWidth} background={this.miniMapColor} document={this._document} tabView={this.tabView} />
-                )}
+                {this.disableMinimap() ? null : <TabMinimapView key="minimap" addDocTab={this.addDocTab} PanelHeight={this.PanelHeight} PanelWidth={this.PanelWidth} background={this.miniMapColor} document={this._document} tabView={this.tabView} />}
             </>
         );
     }
@@ -615,7 +613,7 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
         );
     };
     render() {
-        return (
+        return this.props.document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this.props.document)) || this.props.document?._type_collection !== CollectionViewType.Freeform ? null : (
             <div className="miniMap-hidden">
                 <Popup icon={<FontAwesomeIcon icon="globe-asia" size="lg" />} color={SettingsManager.userVariantColor} type={Type.TERT} onPointerDown={e => e.stopPropagation()} placement={'top-end'} popup={this.popup} />
             </div>
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 182a33fd1..5c7dcc1a4 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -609,10 +609,10 @@ export class CollectionSchemaView extends CollectionSubView() {
         this._menuKeys = this.documentKeys.filter(value => value.toLowerCase().includes(this._menuValue.toLowerCase()));
     };
 
-    getFieldFilters = (field: string) => StrListCast(this.Document._childFilters).filter(filter => filter.split(':')[0] == field);
+    getFieldFilters = (field: string) => StrListCast(this.Document._childFilters).filter(filter => filter.split(Doc.FilterSep)[0] == field);
 
     removeFieldFilters = (field: string) => {
-        this.getFieldFilters(field).forEach(filter => Doc.setDocFilter(this.Document, field, filter.split(':')[1], 'remove'));
+        this.getFieldFilters(field).forEach(filter => Doc.setDocFilter(this.Document, field, filter.split(Doc.FilterSep)[1], 'remove'));
     };
 
     onFilterKeyDown = (e: React.KeyboardEvent) => {
@@ -766,8 +766,8 @@ export class CollectionSchemaView extends CollectionSubView() {
         return keyOptions.map(key => {
             let bool = false;
             if (filters !== undefined) {
-                const ind = filters.findIndex(filter => filter.split(':')[1] === key);
-                const fields = ind === -1 ? undefined : filters[ind].split(':');
+                const ind = filters.findIndex(filter => filter.split(Doc.FilterSep)[1] === key);
+                const fields = ind === -1 ? undefined : filters[ind].split(Doc.FilterSep);
                 bool = fields ? fields[2] === 'check' : false;
             }
             return (
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 1eb6fd51c..0a59818ad 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -246,10 +246,11 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         return (
             <Dropdown
                 selectedVal={text}
-                setSelectedVal={undoable(val => script.script.run({ this: this.layoutDoc, self: this.rootDoc, val }), `dropdown select ${this.label}`)}
+                setSelectedVal={undoable(value => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value }), `dropdown select ${this.label}`)}
                 color={SettingsManager.userColor}
                 background={SettingsManager.userVariantColor}
                 type={Type.TERT}
+                closeOnSelect={false}
                 dropdownType={DropdownType.SELECT}
                 onItemDown={this.dropdownItemDown}
                 items={list}
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 1f113110b..481e43feb 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -119,7 +119,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     public static replayWorkspace(value: Doc) {
         Doc.UserDoc().currentRecording = value;
         value.overlayX = 70;
-        value.overlayY = 590;
+        value.overlayY = window.innerHeight - 180;
         Doc.AddToMyOverlay(value);
         DocumentManager.Instance.AddViewRenderedCb(value, docView => {
             Doc.UserDoc().currentRecording = docView.rootDoc;
@@ -147,11 +147,10 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @action
     public static resumeWorkspaceReplaying(doc: Doc) {
         const docView = DocumentManager.Instance.getDocumentView(doc);
-        const videoBox = docView?.ComponentView as VideoBox;
-        if (videoBox) {
-            videoBox.Play();
-            Doc.UserDoc().workspaceReplayingState = media_state.Playing;
+        if (docView?.ComponentView instanceof VideoBox) {
+            docView.ComponentView.Play();
         }
+        Doc.UserDoc().workspaceReplayingState = media_state.Playing;
     }
 
     @action
-- 
cgit v1.2.3-70-g09d2


From 3929187a6a9ed4031fded51d9c652f705b0ef499 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 13 Sep 2023 16:44:26 -0400
Subject: made grid and snap lines appear on dark backgrounds.  fixed showing
 snap lines based on what's dragged not what's selected.

---
 src/client/views/MainView.tsx                                | 12 ++++++++----
 .../collectionFreeForm/CollectionFreeFormView.tsx            | 10 ++++++++--
 2 files changed, 16 insertions(+), 6 deletions(-)

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

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 2b4f4d5f7..78f6038f9 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -10,13 +10,14 @@ import 'normalize.css';
 import * as React from 'react';
 import { Doc, DocListCast, Opt } from '../../fields/Doc';
 import { DocCast, StrCast } from '../../fields/Types';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents, Utils } from '../../Utils';
+import { emptyFunction, lightOrDark, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents, Utils } from '../../Utils';
 import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager';
 import { DocServer } from '../DocServer';
 import { Docs } from '../documents/Documents';
 import { CollectionViewType, DocumentType } from '../documents/DocumentTypes';
 import { CaptureManager } from '../util/CaptureManager';
 import { DocumentManager } from '../util/DocumentManager';
+import { DragManager } from '../util/DragManager';
 import { GroupManager } from '../util/GroupManager';
 import { HistoryUtil } from '../util/History';
 import { Hypothesis } from '../util/HypothesisUtils';
@@ -911,14 +912,17 @@ export class MainView extends React.Component {
         );
     }
     @computed get snapLines() {
-        return !SelectionManager.Views().some(dv => dv.rootDoc.freeform_snapLines) ? null : (
+        SnappingManager.GetIsDragging();
+        const dragged = DragManager.docsBeingDragged[0];
+        const dragPar = dragged ? DocumentManager.Instance.getDocumentView(dragged)?.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView : undefined;
+        return !dragPar?.rootDoc.freeform_snapLines ? null : (
             <div className="mainView-snapLines">
                 <svg style={{ width: '100%', height: '100%' }}>
                     {SnappingManager.horizSnapLines().map((l, i) => (
-                        <line key={i} x1="0" y1={l} x2="2000" y2={l} stroke="black" opacity={0.3} strokeWidth={0.5} strokeDasharray={'1 1'} />
+                        <line key={i} x1="0" y1={l} x2="2000" y2={l} stroke={lightOrDark(dragPar.rootDoc.backgroundColor ?? 'gray')} opacity={0.3} strokeWidth={1} strokeDasharray={'2 2'} />
                     ))}
                     {SnappingManager.vertSnapLines().map((l, i) => (
-                        <line key={i} y1="0" x1={l} y2="2000" x2={l} stroke="black" opacity={0.3} strokeWidth={0.5} strokeDasharray={'1 1'} />
+                        <line key={i} y1={this.topOfMainDocContent.toString()} x1={l} y2="2000" x2={l} stroke={lightOrDark(dragPar.rootDoc.backgroundColor ?? 'gray')} opacity={0.3} strokeWidth={1} strokeDasharray={'2 2'} />
                     ))}
                 </svg>
             </div>
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 3a4719854..8a812c671 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -16,7 +16,7 @@ import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } fro
 import { ImageField } from '../../../../fields/URLField';
 import { TraceMobx } from '../../../../fields/util';
 import { GestureUtils } from '../../../../pen-gestures/GestureUtils';
-import { aggregateBounds, emptyFunction, intersectRect, returnFalse, returnNone, returnTrue, returnZero, setupMoveUpEvents, Utils } from '../../../../Utils';
+import { aggregateBounds, emptyFunction, intersectRect, lightOrDark, returnFalse, returnNone, returnTrue, returnZero, setupMoveUpEvents, Utils } from '../../../../Utils';
 import { CognitiveServices } from '../../../cognitive_services/CognitiveServices';
 import { Docs, DocUtils } from '../../../documents/Documents';
 import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
@@ -1900,6 +1900,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     showPresPaths = () => (CollectionFreeFormView.ShowPresPaths ? PresBox.Instance.getPaths(this.rootDoc) : null);
 
     brushedView = () => this._brushedView;
+    gridColor = () => {
+        const backColor = this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor + ':box');
+        return lightOrDark(backColor);
+    };
     @computed get marqueeView() {
         TraceMobx();
         return (
@@ -1932,6 +1936,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                                 PanelHeight={this.props.PanelHeight}
                                 panX={this.panX}
                                 panY={this.panY}
+                                color={this.gridColor}
                                 nativeDimScaling={this.nativeDim}
                                 zoomScaling={this.zoomScaling}
                                 layoutDoc={this.layoutDoc}
@@ -2231,6 +2236,7 @@ interface CollectionFreeFormViewBackgroundGridProps {
     panY: () => number;
     PanelWidth: () => number;
     PanelHeight: () => number;
+    color: () => string;
     isAnnotationOverlay?: boolean;
     nativeDimScaling: () => number;
     zoomScaling: () => number;
@@ -2252,7 +2258,7 @@ class CollectionFreeFormBackgroundGrid extends React.Component<CollectionFreeFor
         const renderGridSpace = gridSpace * this.props.zoomScaling();
         const w = this.props.PanelWidth() / this.props.nativeDimScaling() + 2 * renderGridSpace;
         const h = this.props.PanelHeight() / this.props.nativeDimScaling() + 2 * renderGridSpace;
-        const strokeStyle = Doc.ActiveDashboard?.colorScheme === ColorScheme.Dark ? 'rgba(255,255,255,0.5)' : 'rgba(0, 0,0,0.5)';
+        const strokeStyle = this.props.color();
         return !this.props.nativeDimScaling() ? null : (
             <canvas
                 className="collectionFreeFormView-grid"
-- 
cgit v1.2.3-70-g09d2


From 5d95b29c49d46474839c3c221517143b63bc257b Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 14 Sep 2023 10:24:37 -0400
Subject: fixed exception

---
 src/client/views/MainView.tsx           | 2 +-
 src/client/views/nodes/DocumentView.tsx | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

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

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 78f6038f9..957ff4fb5 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -913,7 +913,7 @@ export class MainView extends React.Component {
     }
     @computed get snapLines() {
         SnappingManager.GetIsDragging();
-        const dragged = DragManager.docsBeingDragged[0];
+        const dragged = DragManager.docsBeingDragged.lastElement();
         const dragPar = dragged ? DocumentManager.Instance.getDocumentView(dragged)?.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView : undefined;
         return !dragPar?.rootDoc.freeform_snapLines ? null : (
             <div className="mainView-snapLines">
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index da93a1b13..701d366fa 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -52,7 +52,6 @@ import { LinkAnchorBox } from './LinkAnchorBox';
 import { PresEffect, PresEffectDirection } from './trails';
 import { PinProps, PresBox } from './trails/PresBox';
 import React = require('react');
-import { isThisTypeNode } from 'typescript';
 const { Howl } = require('howler');
 
 interface Window {
-- 
cgit v1.2.3-70-g09d2


From 97424d30199adb56981e150733606c356c0c25e6 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sat, 16 Sep 2023 19:43:05 -0400
Subject: last chance at fixing maps startup.

---
 deploy/index.html                        | 1 -
 src/client/views/MainView.tsx            | 6 ++++++
 src/client/views/nodes/MapBox/MapBox.tsx | 9 ++++-----
 3 files changed, 10 insertions(+), 6 deletions(-)

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

diff --git a/deploy/index.html b/deploy/index.html
index c23deabd3..b345e193f 100644
--- a/deploy/index.html
+++ b/deploy/index.html
@@ -10,7 +10,6 @@
         <link rel="shortcut icon" type="image/jpg" href="./assets/favicon.png" />
         <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous" />
         <script src="https://cdnjs.cloudflare.com/ajax/libs/typescript/3.3.1/typescript.min.js"></script>
-        <script type="text/javascript" src="http://www.bing.com/api/maps/mapcontrol?callback=GetMap&key=[YOUR_BING_MAPS_KEY]" async defer></script>
 
         <script>
             function getCookie(cname) {
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 957ff4fb5..707cf3a34 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -144,6 +144,12 @@ export class MainView extends React.Component {
     mainDocViewHeight = () => this._dashUIHeight - this.headerBarDocHeight();
 
     componentDidMount() {
+        const scriptTag = document.createElement('script');
+        scriptTag.setAttribute('type', 'text/javascript');
+        scriptTag.setAttribute('src', 'https://www.bing.com/api/maps/mapcontrol?callback=makeMap');
+        scriptTag.async = true;
+        scriptTag.defer = true;
+        document.body.appendChild(scriptTag);
         document.getElementById('root')?.addEventListener('scroll', e => (ele => (ele.scrollLeft = ele.scrollTop = 0))(document.getElementById('root')!));
         const ele = document.getElementById('loader');
         const prog = document.getElementById('dash-progress');
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index 0842485ee..b54157593 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -106,6 +106,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     componentWillUnmount(): void {
         this._unmounting = true;
         this.deselectPin();
+        this._rerenderTimeout && clearTimeout(this._rerenderTimeout);
         Object.keys(this._disposers).forEach(key => this._disposers[key]?.());
     }
 
@@ -690,22 +691,20 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     searchbarKeyDown = (e: any) => e.key === 'Enter' && this.bingSearch();
 
     static _firstRender = true;
-    static _rerenderDelay = 0;
+    static _rerenderDelay = 500;
     _rerenderTimeout: any;
     render() {
         // bcz:  no idea what's going on here, but bings maps have some kind of bug
         // such that we need to delay rendering a second map on startup until the first map is rendered.
         this.rootDoc[DocCss];
-        if (MapBox._firstRender) {
-            MapBox._firstRender = false;
-            MapBox._rerenderDelay = 500;
-        } else if (MapBox._rerenderDelay) {
+        if (MapBox._rerenderDelay) {
             // prettier-ignore
             this._rerenderTimeout = this._rerenderTimeout ??
                 setTimeout(action(() => {
                     if ((window as any).Microsoft?.Maps) {
                         MapBox._rerenderDelay = 0;
                     }
+                    this._rerenderTimeout = undefined;
                     this.rootDoc[DocCss] = this.rootDoc[DocCss] + 1;
                 }), MapBox._rerenderDelay);
             return null;
-- 
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/MainView.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


From b6920e6ffc50eb46f3ac3657c9d5b4fe45e1dd0a Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 20 Sep 2023 01:25:40 -0400
Subject: shifted carousel fwd/back buttons away from edges of screen.  made
 caption width of carousel inset by 30.  made 3d carousel images bigger
 vertically.  made  properties dragger handle smaller when minimized.

---
 src/client/util/CurrentUserUtils.ts                |  2 +-
 src/client/views/MainView.scss                     |  6 +++++-
 src/client/views/MainView.tsx                      |  6 +++++-
 .../collections/CollectionCarousel3DView.scss      |  4 ++--
 .../views/collections/CollectionCarouselView.scss  | 23 +++++++++++-----------
 .../views/collections/CollectionCarouselView.tsx   | 16 ++++++++-------
 src/client/views/global/globalCssVariables.scss    |  2 +-
 7 files changed, 35 insertions(+), 24 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index cbdc2fc81..259c028cc 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -707,8 +707,8 @@ export class CurrentUserUtils {
                     CollectionViewType.Grid, CollectionViewType.NoteTaking]),
               title: "Perspective",                    toolTip: "View",                 btnType: ButtonType.DropdownList,                                                                                                                                    ignoreClick: true, width: 100, scripts: { script:  'setView(value, _readOnly_)'}},
             { title: "Pin",     icon: "map-pin",       toolTip: "Pin View to Trail",    btnType: ButtonType.ClickButton,         expertMode: false,                                                                                                                             width: 30,  scripts: { onClick: 'pinWithView(altKey)'}, funcs: {hidden: "IsNoneSelected()"}},
-            { title: "Fill",    icon: "fill-drip",     toolTip: "Background Fill Color",btnType: ButtonType.ColorButton,         expertMode: false,                                                                                                          ignoreClick: true, width: 30,  scripts: { script:  'return setBackgroundColor(value, _readOnly_)'}, funcs: {hidden: "IsNoneSelected()"}}, // Only when a document is selected
             { title: "Header",  icon: "heading",       toolTip: "Header Color",         btnType: ButtonType.ColorButton,         expertMode: true,                                                                                                           ignoreClick: true,             scripts: { script:  'return setHeaderColor(value, _readOnly_)'}, funcs: {hidden: "IsNoneSelected()"}},
+            { title: "Fill",    icon: "fill-drip",     toolTip: "Background Fill Color",btnType: ButtonType.ColorButton,         expertMode: false,                                                                                                          ignoreClick: true, width: 30,  scripts: { script:  'return setBackgroundColor(value, _readOnly_)'}, funcs: {hidden: "IsNoneSelected()"}}, // Only when a document is selected
             { title: "Overlay", icon: "layer-group",   toolTip: "Overlay",              btnType: ButtonType.ToggleButton,        expertMode: true,  toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(self.toolType, self.expertMode, true)'},       scripts: { onClick: '{ return toggleOverlay(_readOnly_); }'}}, // Only when floating document is selected in freeform
             { title: "Back",    icon: "chevron-left",  toolTip: "Prev Animation Frame", btnType: ButtonType.ClickButton,         expertMode: true,  toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(self.toolType, self.expertMode)'}, width: 30,  scripts: { onClick: 'prevKeyFrame(_readOnly_)'}},
             { title: "Num",     icon:"",               toolTip: "Frame Number (click to toggle edit mode)",    btnType: ButtonType.TextButton,          expertMode: true,  toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectionManager_selectedDocType(self.toolType, self.expertMode)', buttonText: 'selectedDocs()?.lastElement()?.currentFrame?.toString()'}, width: 20, scripts: { onClick: '{ return curKeyFrame(_readOnly_);}'}},
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index 98367969b..4fb2ac279 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -96,6 +96,7 @@ h1,
     top: 0;
 }
 
+.mainView-propertiesDragger-minified,
 .mainView-propertiesDragger {
     //background-color: rgb(140, 139, 139);
     background-color: $light-gray;
@@ -108,9 +109,9 @@ h1,
     border-bottom-left-radius: 10px;
     border-right: unset;
     z-index: 41; // lm_maximised has a z-index of 40 and this needs to be above that
-    display: flex;
     align-items: center;
     padding: 4px;
+    display: flex;
 
     .mainView-propertiesDragger-icon {
         width: 10px;
@@ -124,6 +125,9 @@ h1,
         cursor: grab;
     }
 }
+.mainView-propertiesDragger-minified {
+    width: 10px;
+}
 
 .mainView-innerContent {
     display: contents;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 6d08c01fa..d6f5d63fe 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -809,7 +809,11 @@ export class MainView extends React.Component {
                         {this.dockingContent}
 
                         {this._hideUI ? null : (
-                            <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ background: SettingsManager.userVariantColor, right: this.propertiesWidth() - 1 }}>
+                            <div
+                                className={`mainView-propertiesDragger${this.propertiesWidth() < 10 ? '-minified' : ''}`}
+                                key="props"
+                                onPointerDown={this.onPropertiesPointerDown}
+                                style={{ background: SettingsManager.userVariantColor, right: this.propertiesWidth() - 1 }}>
                                 <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={SettingsManager.userColor} size="sm" />
                             </div>
                         )}
diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss
index 6bd1d9f5f..7622043e3 100644
--- a/src/client/views/collections/CollectionCarousel3DView.scss
+++ b/src/client/views/collections/CollectionCarousel3DView.scss
@@ -87,13 +87,13 @@
 .carousel3DView-fwd,
 .carousel3DView-fwd-scroll,
 .carousel3DView-fwd-scroll-hidden {
-    right: 0;
+    right: 20;
 }
 
 .carousel3DView-back,
 .carousel3DView-back-scroll,
 .carousel3DView-back-scroll-hidden {
-    left: 0;
+    left: 20;
 }
 
 .carousel3DView-fwd-scroll-hidden,
diff --git a/src/client/views/collections/CollectionCarouselView.scss b/src/client/views/collections/CollectionCarouselView.scss
index 8660113cd..130b31325 100644
--- a/src/client/views/collections/CollectionCarouselView.scss
+++ b/src/client/views/collections/CollectionCarouselView.scss
@@ -1,8 +1,7 @@
-
 .collectionCarouselView-outer {
-    height : 100%;
+    height: 100%;
     .collectionCarouselView-caption {
-        height: 50; 
+        height: 50;
         display: inline-block;
         width: 100%;
     }
@@ -13,7 +12,8 @@
         user-select: none;
     }
 }
-.carouselView-back, .carouselView-fwd  {
+.carouselView-back,
+.carouselView-fwd {
     position: absolute;
     display: flex;
     top: 42.5%;
@@ -22,18 +22,19 @@
     align-items: center;
     border-radius: 5px;
     justify-content: center;
-    color: rgba(255,255,255,0.5);
-    background : rgba(0,0,0, 0.1);
+    color: rgba(255, 255, 255, 0.5);
+    background: rgba(0, 0, 0, 0.1);
     &:hover {
-        color:white;
+        color: white;
     }
 }
 .carouselView-fwd {
-    right: 0; 
+    right: 20;
 }
 .carouselView-back {
-    left: 0; 
+    left: 20;
 }
-.carouselView-back:hover, .carouselView-fwd:hover {
+.carouselView-back:hover,
+.carouselView-fwd:hover {
     background: lightgray;
-}
\ No newline at end of file
+}
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index 7fa36d228..040a584b8 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -4,7 +4,7 @@ import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, Opt } from '../../../fields/Doc';
 import { NumCast, ScriptCast, StrCast } from '../../../fields/Types';
-import { emptyFunction, returnFalse, returnZero, StopEvent } from '../../../Utils';
+import { emptyFunction, returnFalse, returnOne, returnZero, StopEvent } from '../../../Utils';
 import { DragManager } from '../../util/DragManager';
 import { DocumentView, DocumentViewProps } from '../nodes/DocumentView';
 import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
@@ -44,12 +44,14 @@ export class CollectionCarouselView extends CollectionSubView() {
     panelHeight = () => this.props.PanelHeight() - (StrCast(this.layoutDoc._layout_showCaption) ? 50 : 0);
     onContentDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick);
     onContentClick = () => ScriptCast(this.layoutDoc.onChildClick);
+    @computed get marginX() {
+        return NumCast(this.layoutDoc.caption_xMargin, 50);
+    }
+    captionWidth = () => this.props.PanelWidth() - 2 * this.marginX;
     @computed get content() {
         const index = NumCast(this.layoutDoc._carousel_index);
         const curDoc = this.childLayoutPairs?.[index];
-        const captionProps = { ...this.props, fieldKey: 'caption', setHeight: undefined, setContentView: undefined };
-        const marginX = NumCast(this.layoutDoc['caption_xMargin']);
-        const marginY = NumCast(this.layoutDoc['caption_yMargin']);
+        const captionProps = { ...this.props, NativeScaling: returnOne, PanelWidth: this.captionWidth, fieldKey: 'caption', setHeight: undefined, setContentView: undefined };
         const show_captions = StrCast(this.layoutDoc._layout_showCaption);
         return !(curDoc?.layout instanceof Doc) ? null : (
             <>
@@ -80,9 +82,9 @@ export class CollectionCarouselView extends CollectionSubView() {
                     style={{
                         display: show_captions ? undefined : 'none',
                         borderRadius: this.props.styleProvider?.(this.layoutDoc, captionProps, StyleProp.BorderRounding),
-                        marginRight: marginX,
-                        marginLeft: marginX,
-                        width: `calc(100% - ${marginX * 2}px)`,
+                        marginRight: this.marginX,
+                        marginLeft: this.marginX,
+                        width: `calc(100% - ${this.marginX * 2}px)`,
                     }}>
                     <FormattedTextBox key={index} {...captionProps} allowScroll={true} fieldKey={show_captions} styleProvider={this.captionStyleProvider} Document={curDoc.layout} DataDoc={undefined} />
                 </div>
diff --git a/src/client/views/global/globalCssVariables.scss b/src/client/views/global/globalCssVariables.scss
index 7b2ac5713..ddd99c836 100644
--- a/src/client/views/global/globalCssVariables.scss
+++ b/src/client/views/global/globalCssVariables.scss
@@ -71,7 +71,7 @@ $LEFT_MENU_WIDTH: 60px;
 $TREE_BULLET_WIDTH: 20px;
 
 $CAROUSEL3D_CENTER_SCALE: 1.3;
-$CAROUSEL3D_SIDE_SCALE: 0.3;
+$CAROUSEL3D_SIDE_SCALE: 0.6;
 $CAROUSEL3D_TOP: 15;
 
 :export {
-- 
cgit v1.2.3-70-g09d2


From 0df1fc3fd85c1dea84dcaec5a934fc08f0da6832 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 4 Oct 2023 07:46:05 -0400
Subject: several fixes for webclips, linking to pdf/web, fonticon dropdowns.
 removed sliderbox. reduce uses of scriptContext

fixed web clipping annotations to be in correct spot and not to crash because of using a url that it doesn't have.
fixed pdf/web links to not use anchor from other end of link. because of sharing of GetAnchor global.
added a backup when presbox overwrites a doc's data field.
removed sliderBox.
fixed fontIcon dropdowns to not call click script twice.
removed scriptContext where it wasn't needed which is everywhere except TreeViews.
---
 src/client/documents/DocumentTypes.ts              |   3 +-
 src/client/documents/Documents.ts                  |   8 --
 src/client/util/CurrentUserUtils.ts                |   2 +-
 src/client/views/MainView.tsx                      |   2 -
 src/client/views/StyleProvider.tsx                 |   2 -
 .../views/collections/CollectionNoteTakingView.tsx |   1 -
 .../collections/CollectionStackedTimeline.tsx      |  37 +++-----
 .../views/collections/CollectionStackingView.tsx   |   1 -
 .../collectionSchema/CollectionSchemaView.tsx      |   1 -
 src/client/views/nodes/DocumentContentsView.tsx    |   2 -
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |   1 -
 src/client/views/nodes/PDFBox.tsx                  |   2 +-
 src/client/views/nodes/SliderBox.scss              |  19 ----
 src/client/views/nodes/SliderBox.tsx               | 103 ---------------------
 src/client/views/nodes/WebBox.scss                 |   1 -
 src/client/views/nodes/WebBox.tsx                  |  80 +++++++++++-----
 src/client/views/nodes/trails/PresBox.tsx          |   7 +-
 src/client/views/pdf/PDFViewer.tsx                 |   5 +-
 18 files changed, 82 insertions(+), 195 deletions(-)
 delete mode 100644 src/client/views/nodes/SliderBox.scss
 delete mode 100644 src/client/views/nodes/SliderBox.tsx

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

diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts
index f8d129e79..87010f770 100644
--- a/src/client/documents/DocumentTypes.ts
+++ b/src/client/documents/DocumentTypes.ts
@@ -30,14 +30,13 @@ export enum DocumentType {
     // special purpose wrappers that either take no data or are compositions of lower level types
     LINK = 'link',
     IMPORT = 'import',
-    SLIDER = 'slider',
     PRES = 'presentation',
     PRESELEMENT = 'preselement',
     COLOR = 'color',
     YOUTUBE = 'youtube',
     COMPARISON = 'comparison',
     GROUP = 'group',
-    PUSHPIN = "pushpin",
+    PUSHPIN = 'pushpin',
 
     SCRIPTDB = 'scriptdb', // database of scripts
     GROUPDB = 'groupdb', // database of groups
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index f7ceef4f4..a79a62b57 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -54,7 +54,6 @@ import { PhysicsSimulationBox } from '../views/nodes/PhysicsBox/PhysicsSimulatio
 import { RecordingBox } from '../views/nodes/RecordingBox/RecordingBox';
 import { ScreenshotBox } from '../views/nodes/ScreenshotBox';
 import { ScriptingBox } from '../views/nodes/ScriptingBox';
-import { SliderBox } from '../views/nodes/SliderBox';
 import { TaskCompletionBox } from '../views/nodes/TaskCompletedBox';
 import { PresBox } from '../views/nodes/trails/PresBox';
 import { PresElementBox } from '../views/nodes/trails/PresElementBox';
@@ -628,13 +627,6 @@ export namespace Docs {
                     options: {},
                 },
             ],
-            [
-                DocumentType.SLIDER,
-                {
-                    layout: { view: SliderBox, dataField: defaultDataKey },
-                    options: {},
-                },
-            ],
             [
                 DocumentType.PRES,
                 {
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 2ea5972ee..cc8f72ddf 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -820,7 +820,7 @@ export class CurrentUserUtils {
     // When the user views one of these documents, it will be added to the sharing documents 'viewed' list field
     // The sharing document also stores the user's color value which helps distinguish shared documents from personal documents
     static setupSharedDocs(doc: Doc, sharingDocumentId: string) {
-        const dblClkScript = "{scriptContext.openLevel(documentView); addDocToList(scriptContext.props.treeView.props.Document, 'viewed', documentView.rootDoc);}";
+        const dblClkScript = "{scriptContext.openLevel(documentView); addDocToList(documentView.props.treeViewDoc, 'viewed', documentView.rootDoc);}";
         
         const sharedScripts = {  treeView_ChildDoubleClick: dblClkScript,  }
         const sharedDocOpts:DocumentOptions = {
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index d6f5d63fe..0a3389fc2 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -728,7 +728,6 @@ export class MainView extends React.Component {
                         PanelHeight={this.leftMenuFlyoutHeight}
                         renderDepth={0}
                         isContentActive={returnTrue}
-                        scriptContext={CollectionDockingView.Instance?.props.Document}
                         focus={emptyFunction}
                         whenChildContentsActiveChanged={emptyFunction}
                         bringToFront={emptyFunction}
@@ -766,7 +765,6 @@ export class MainView extends React.Component {
                     childFilters={returnEmptyFilter}
                     childFiltersByRanges={returnEmptyFilter}
                     searchFilterDocs={returnEmptyDoclist}
-                    scriptContext={this}
                 />
             </div>
         );
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index d7537bffb..8417a6f5b 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -21,7 +21,6 @@ import { InkingStroke } from './InkingStroke';
 import { DocumentView, DocumentViewProps } from './nodes/DocumentView';
 import { FieldViewProps } from './nodes/FieldView';
 import { KeyValueBox } from './nodes/KeyValueBox';
-import { SliderBox } from './nodes/SliderBox';
 import './StyleProvider.scss';
 import React = require('react');
 import { PropertiesView } from './PropertiesView';
@@ -215,7 +214,6 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                 case DocumentType.SCREENSHOT:
                 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)
                             ? SettingsManager.userBackgroundColor
                             : doc.annotationOn
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index a69049b59..c7ad80f11 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -269,7 +269,6 @@ export class CollectionNoteTakingView extends CollectionSubView() {
                 whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
                 addDocTab={this.props.addDocTab}
                 bringToFront={returnFalse}
-                scriptContext={this.props.scriptContext}
                 pinToPres={this.props.pinToPres}
             />
         );
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index ad3160a08..c4650647c 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -58,9 +58,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
     @observable static SelectingRegion: CollectionStackedTimeline | undefined = undefined;
     @observable public static CurrentlyPlaying: DocumentView[];
 
-    static RangeScript: ScriptField;
     static LabelScript: ScriptField;
-    static RangePlayScript: ScriptField;
     static LabelPlayScript: ScriptField;
 
     private _timeline: HTMLDivElement | null = null; // ref to actual timeline div
@@ -114,25 +112,6 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
         return this._zoomFactor;
     }
 
-    constructor(props: any) {
-        super(props);
-        // onClick play scripts
-        CollectionStackedTimeline.RangeScript =
-            CollectionStackedTimeline.RangeScript ||
-            ScriptField.MakeFunction(`scriptContext.clickAnchor(this, clientX)`, {
-                self: Doc.name,
-                scriptContext: 'any',
-                clientX: 'number',
-            })!;
-        CollectionStackedTimeline.RangePlayScript =
-            CollectionStackedTimeline.RangePlayScript ||
-            ScriptField.MakeFunction(`scriptContext.playOnClick(this, clientX)`, {
-                self: Doc.name,
-                scriptContext: 'any',
-                clientX: 'number',
-            })!;
-    }
-
     componentDidMount() {
         document.addEventListener('keydown', this.keyEvents, true);
     }
@@ -179,8 +158,19 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
         return Math.max(this.clipStart, Math.min(this.clipEnd, (screen_delta / width) * this.clipDuration + this.clipStart));
     };
 
-    rangeClickScript = () => CollectionStackedTimeline.RangeScript;
-    rangePlayScript = () => CollectionStackedTimeline.RangePlayScript;
+    @computed get rangeClick() {
+        // prettier-ignore
+        return ScriptField.MakeFunction('stackedTimeline.clickAnchor(this, clientX)',
+            { stackedTimeline: 'any', clientX: 'number' }, { stackedTimeline: this as any }
+        )!;
+    }
+    @computed get rangePlay() {
+        // prettier-ignore
+        return ScriptField.MakeFunction('stackedTimeline.playOnClick(this, clientX)', 
+            { stackedTimeline: 'any', clientX: 'number' }, { stackedTimeline: this as any })!;
+    }
+    rangeClickScript = () => this.rangeClick;
+    rangePlayScript = () => this.rangePlay;
 
     // handles key events for for creating key anchors, scrubbing, exiting trim
     @action
@@ -835,7 +825,6 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
                     hideResizeHandles={true}
                     bringToFront={emptyFunction}
                     contextMenuItems={this.contextMenuItems}
-                    scriptContext={this.props.stackedTimeline}
                 />
             ),
         };
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 36f8bc101..c43a9d2b8 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -361,7 +361,6 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
                 whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
                 addDocTab={this.props.addDocTab}
                 bringToFront={returnFalse}
-                scriptContext={this.props.scriptContext}
                 pinToPres={this.props.pinToPres}
             />
         );
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index d2b61167e..f73c037f4 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -972,7 +972,6 @@ class CollectionSchemaViewDocs extends React.Component<CollectionSchemaViewDocsP
                                 hideDocumentButtonBar={true}
                                 hideLinkAnchors={true}
                                 layout_fitWidth={returnTrue}
-                                scriptContext={this}
                             />
                         </div>
                     );
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 8ac9d6804..e1de2fa76 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -41,7 +41,6 @@ import { PhysicsSimulationBox } from './PhysicsBox/PhysicsSimulationBox';
 import { RecordingBox } from './RecordingBox';
 import { ScreenshotBox } from './ScreenshotBox';
 import { ScriptingBox } from './ScriptingBox';
-import { SliderBox } from './SliderBox';
 import { PresBox } from './trails/PresBox';
 import { VideoBox } from './VideoBox';
 import { WebBox } from './WebBox';
@@ -240,7 +239,6 @@ export class DocumentContentsView extends React.Component<
                     FontIconBox,
                     LabelBox,
                     EquationBox,
-                    SliderBox,
                     FieldView,
                     CollectionFreeFormView,
                     CollectionDockingView,
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 14a3d16ef..d2e1293da 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -240,7 +240,6 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
                 text: typeof value === 'string' ? value.charAt(0).toUpperCase() + value.slice(1) : StrCast(DocCast(value)?.title),
                 val: value,
                 style: getStyle(value),
-                onClick: undoable(() => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value }), value),
                 // shortcut: '#',
             }));
 
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 73a5be90a..cf44649a2 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -242,7 +242,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                 title: StrCast(this.rootDoc.title + '@' + NumCast(this.layoutDoc._layout_scrollTop)?.toFixed(0)),
                 annotationOn: this.rootDoc,
             });
-        const visibleAnchor = this._pdfViewer?._getAnchor(this._pdfViewer.savedAnnotations(), true);
+        const visibleAnchor = this._pdfViewer?._getAnchor?.(this._pdfViewer.savedAnnotations(), true);
         const anchor = visibleAnchor ?? docAnchor();
         PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: true, pannable: true } }, this.rootDoc);
         anchor.text = ele?.textContent ?? '';
diff --git a/src/client/views/nodes/SliderBox.scss b/src/client/views/nodes/SliderBox.scss
deleted file mode 100644
index 4206a368d..000000000
--- a/src/client/views/nodes/SliderBox.scss
+++ /dev/null
@@ -1,19 +0,0 @@
-.sliderBox-outerDiv {
-    width: calc(100% - 14px);   // 14px accounts for handles that are at the max value of the slider that would extend outside the box
-    height: 100%;
-    border-radius: inherit;
-    display: flex;
-    flex-direction: column;
-    position: relative;
-    .slider-tracks {
-        top: 7px;
-        position: relative;
-    }
-    .slider-ticks {
-        position: relative;
-    }
-    .slider-handles {
-        top: 7px;
-        position: relative;
-    }
-}
\ No newline at end of file
diff --git a/src/client/views/nodes/SliderBox.tsx b/src/client/views/nodes/SliderBox.tsx
deleted file mode 100644
index 430b20eb5..000000000
--- a/src/client/views/nodes/SliderBox.tsx
+++ /dev/null
@@ -1,103 +0,0 @@
-import { runInAction } from 'mobx';
-import { observer } from 'mobx-react';
-import * as React from 'react';
-import { Handles, Rail, Slider, Ticks, Tracks } from 'react-compound-slider';
-import { NumCast, ScriptCast, StrCast } from '../../../fields/Types';
-import { ContextMenu } from '../ContextMenu';
-import { ContextMenuProps } from '../ContextMenuItem';
-import { ViewBoxBaseComponent } from '../DocComponent';
-import { ScriptBox } from '../ScriptBox';
-import { StyleProp } from '../StyleProvider';
-import { FieldView, FieldViewProps } from './FieldView';
-import { Handle, Tick, TooltipRail, Track } from './SliderBox-components';
-import './SliderBox.scss';
-
-@observer
-export class SliderBox extends ViewBoxBaseComponent<FieldViewProps>() {
-    public static LayoutString(fieldKey: string) {
-        return FieldView.LayoutString(SliderBox, fieldKey);
-    }
-
-    get minThumbKey() {
-        return this.fieldKey + '-minThumb';
-    }
-    get maxThumbKey() {
-        return this.fieldKey + '-maxThumb';
-    }
-    get minKey() {
-        return this.fieldKey + '-min';
-    }
-    get maxKey() {
-        return this.fieldKey + '-max';
-    }
-    specificContextMenu = (e: React.MouseEvent): void => {
-        const funcs: ContextMenuProps[] = [];
-        funcs.push({ description: 'Edit Thumb Change Script', icon: 'edit', event: (obj: any) => ScriptBox.EditButtonScript('On Thumb Change ...', this.props.Document, 'onThumbChange', obj.x, obj.y) });
-        ContextMenu.Instance.addItem({ description: 'Options...', subitems: funcs, icon: 'asterisk' });
-    };
-    onChange = (values: readonly number[]) =>
-        runInAction(() => {
-            this.dataDoc[this.minThumbKey] = values[0];
-            this.dataDoc[this.maxThumbKey] = values[1];
-            ScriptCast(this.layoutDoc.onThumbChanged, null)?.script.run({
-                self: this.rootDoc,
-                scriptContext: this.props.scriptContext,
-                range: values,
-                this: this.layoutDoc,
-            });
-        });
-
-    render() {
-        const domain = [NumCast(this.layoutDoc[this.minKey]), NumCast(this.layoutDoc[this.maxKey])];
-        const defaultValues = [NumCast(this.dataDoc[this.minThumbKey]), NumCast(this.dataDoc[this.maxThumbKey])];
-        return domain[1] <= domain[0] ? null : (
-            <div className="sliderBox-outerDiv" onContextMenu={this.specificContextMenu} onPointerDown={e => e.stopPropagation()} style={{ boxShadow: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BoxShadow) }}>
-                <div
-                    className="sliderBox-mainButton"
-                    onContextMenu={this.specificContextMenu}
-                    style={{
-                        background: StrCast(this.layoutDoc.backgroundColor),
-                        color: StrCast(this.layoutDoc.color, 'black'),
-                        fontSize: StrCast(this.layoutDoc._text_fontSize),
-                        letterSpacing: StrCast(this.layoutDoc.letterSpacing),
-                    }}>
-                    <Slider mode={2} step={Math.min(1, 0.1 * (domain[1] - domain[0]))} domain={domain} rootStyle={{ position: 'relative', width: '100%' }} onChange={this.onChange} values={defaultValues}>
-                        <Rail>{railProps => <TooltipRail {...railProps} />}</Rail>
-                        <Handles>
-                            {({ handles, activeHandleID, getHandleProps }) => (
-                                <div className="slider-handles">
-                                    {handles.map((handle, i) => {
-                                        const value = i === 0 ? defaultValues[0] : defaultValues[1];
-                                        return (
-                                            <div title={String(value)}>
-                                                <Handle key={handle.id} handle={handle} domain={domain} isActive={handle.id === activeHandleID} getHandleProps={getHandleProps} />
-                                            </div>
-                                        );
-                                    })}
-                                </div>
-                            )}
-                        </Handles>
-                        <Tracks left={false} right={false}>
-                            {({ tracks, getTrackProps }) => (
-                                <div className="slider-tracks">
-                                    {tracks.map(({ id, source, target }) => (
-                                        <Track key={id} source={source} target={target} disabled={false} getTrackProps={getTrackProps} />
-                                    ))}
-                                </div>
-                            )}
-                        </Tracks>
-                        <Ticks count={5}>
-                            {({ ticks }) => (
-                                <div className="slider-ticks">
-                                    {ticks.map(tick => (
-                                        <Tick key={tick.id} tick={tick} count={ticks.length} format={(val: number) => val.toString()} />
-                                    ))}
-                                </div>
-                            )}
-                        </Ticks>
-                    </Slider>
-                </div>
-            </div>
-        );
-    }
-}
diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss
index 75847c100..511c91da0 100644
--- a/src/client/views/nodes/WebBox.scss
+++ b/src/client/views/nodes/WebBox.scss
@@ -176,7 +176,6 @@
             width: 100%;
             height: 100%;
             transform-origin: top left;
-            overflow: auto;
 
             .webBox-iframe {
                 width: 100%;
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 27c19105f..d4ba7a48f 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -62,10 +62,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     private _searchRef = React.createRef<HTMLInputElement>();
     private _searchString = '';
     private _scrollTimer: any;
+    private _getAnchor: (savedAnnotations: Opt<ObservableMap<number, HTMLDivElement[]>>, addAsAnnotation: boolean) => Opt<Doc> = () => undefined;
 
-    private get _getAnchor() {
-        return AnchorMenu.Instance?.GetAnchor;
-    }
     @observable private _webUrl = ''; // url of the src parameter of the embedded iframe but not necessarily the rendered page - eg, when following a link, the rendered page changes but we don't want the src parameter to also change as that would cause an unnecessary re-render.
     @observable private _hackHide = false; // apparently changing the value of the 'sandbox' prop doesn't necessarily apply it to the active iframe.  so thisforces the ifrmae to be rebuilt when allowScripts is toggled
     @observable private _searching: boolean = false;
@@ -186,13 +184,15 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         this.props.setContentView?.(this); // this tells the DocumentView that this WebBox is the "content" of the document.  this allows the DocumentView to call WebBox relevant methods to configure the UI (eg, show back/forward buttons)
 
         runInAction(() => {
-            this._annotationKeySuffix = () => this._urlHash + '_annotations';
-            const reqdFuncs: { [key: string]: string } = {};
+            this._annotationKeySuffix = () => (this._urlHash ? this._urlHash + '_' : '') + 'annotations';
             // bcz: need to make sure that doc.data_annotations points to the currently active web page's annotations (this could/should be when the doc is created)
-            reqdFuncs[this.fieldKey + '_annotations'] = `copyField(this["${this.fieldKey}_"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"_annotations"])`;
-            reqdFuncs[this.fieldKey + '_annotations-setter'] = `this["${this.fieldKey}_"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"_annotations"] = value`;
-            reqdFuncs[this.fieldKey + '_sidebar'] = `copyField(this["${this.fieldKey}_"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"_sidebar"])`;
-            DocUtils.AssignScripts(this.dataDoc, {}, reqdFuncs);
+            if (this._url) {
+                const reqdFuncs: { [key: string]: string } = {};
+                reqdFuncs[this.fieldKey + '_annotations'] = `copyField(this["${this.fieldKey}_"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"annotations"])`;
+                reqdFuncs[this.fieldKey + '_annotations-setter'] = `this["${this.fieldKey}_"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"annotations"] = value`;
+                reqdFuncs[this.fieldKey + '_sidebar'] = `copyField(this["${this.fieldKey}_"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"sidebar"])`;
+                DocUtils.AssignScripts(this.dataDoc, {}, reqdFuncs);
+            }
         });
         this._disposers.urlchange = reaction(
             () => WebCast(this.rootDoc.data),
@@ -264,14 +264,16 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             const clientRects = selRange.getClientRects();
             for (let i = 0; i < clientRects.length; i++) {
                 const rect = clientRects.item(i);
+                const mainrect = this._url ? { translateX: 0, translateY: 0, scale: 1 } : Utils.GetScreenTransform(this._mainCont.current);
                 if (rect && rect.width !== this._mainCont.current.clientWidth) {
                     const annoBox = document.createElement('div');
                     annoBox.className = 'marqueeAnnotator-annotationBox';
+                    const scale = this._url ? 1 : this.props.ScreenToLocalTransform().Scale;
                     // transforms the positions from screen onto the pdf div
-                    annoBox.style.top = (rect.top + this._mainCont.current.scrollTop).toString();
-                    annoBox.style.left = rect.left.toString();
-                    annoBox.style.width = rect.width.toString();
-                    annoBox.style.height = rect.height.toString();
+                    annoBox.style.top = ((rect.top - mainrect.translateY) * scale + (this._url ? this._mainCont.current.scrollTop : NumCast(this.layoutDoc.layout_scrollTop))).toString();
+                    annoBox.style.left = ((rect.left - mainrect.translateX) * scale).toString();
+                    annoBox.style.width = (rect.width * scale).toString();
+                    annoBox.style.height = (rect.height * scale).toString();
                     this._annotationLayer.current && MarqueeAnnotator.previewNewAnnotation(this._savedAnnotations, this._annotationLayer.current, annoBox, 1);
                 }
             }
@@ -340,7 +342,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             });
         PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: pinProps?.pinData ? true : false, pannable: true } }, this.rootDoc);
         anchor.text = ele?.textContent ?? '';
-        anchor.text_html = ele?.innerHTML;
+        anchor.text_html = ele?.innerHTML ?? this._selectionText;
         addAsAnnotation && this.addDocumentWrapper(anchor);
         return anchor;
     };
@@ -362,12 +364,49 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                 this._textAnnotationCreator = () => this.createTextAnnotation(sel, !sel.isCollapsed ? sel.getRangeAt(0) : undefined);
                 AnchorMenu.Instance.jumpTo(e.clientX * scale + mainContBounds.translateX, e.clientY * scale + mainContBounds.translateY - NumCast(this.layoutDoc._layout_scrollTop) * scale);
                 // Changing which document to add the annotation to (the currently selected WebBox)
-                GPTPopup.Instance.setSidebarId(`${this.props.fieldKey}_${this._urlHash}_sidebar`);
+                GPTPopup.Instance.setSidebarId(`${this.props.fieldKey}_${this._urlHash ? this._urlHash + '_' : ''}sidebar`);
                 GPTPopup.Instance.addDoc = this.sidebarAddDocument;
             }
         }
     };
     @action
+    webClipDown = (e: React.PointerEvent) => {
+        const mainContBounds = Utils.GetScreenTransform(this._mainCont.current!);
+        const scale = (this.props.NativeDimScaling?.() || 1) * mainContBounds.scale;
+        const word = getWordAtPoint(e.target, e.clientX, e.clientY);
+        this._setPreviewCursor?.(e.clientX, e.clientY, false, true, this.rootDoc);
+        MarqueeAnnotator.clearAnnotations(this._savedAnnotations);
+        e.button !== 2 && (this._marqueeing = [e.clientX, e.clientY]);
+        if (word || (e.target as any)?.className?.includes('rangeslider') || (e.target as any)?.onclick || (e.target as any)?.parentNode?.onclick) {
+            e.stopPropagation();
+            setTimeout(
+                action(() => (this._marqueeing = undefined)),
+                100
+            ); // bcz: hack .. anchor menu is setup within MarqueeAnnotator so we need to at least create the marqueeAnnotator even though we aren't using it.
+        } else {
+            this._isAnnotating = true;
+            this.props.select(false);
+            e.stopPropagation();
+            e.preventDefault();
+        }
+        document.addEventListener('pointerup', this.webClipUp);
+    };
+    webClipUp = (e: PointerEvent) => {
+        document.removeEventListener('pointerup', this.webClipUp);
+        this._getAnchor = AnchorMenu.Instance?.GetAnchor; // need to save AnchorMenu's getAnchor since a subsequent selection on another doc will overwrite this value
+        const sel = window.getSelection();
+        if (sel && !sel.isCollapsed) {
+            const selRange = sel.getRangeAt(0);
+            this._selectionText = sel.toString();
+            AnchorMenu.Instance.setSelectedText(sel.toString());
+            this._textAnnotationCreator = () => this.createTextAnnotation(sel, selRange);
+            AnchorMenu.Instance.jumpTo(e.clientX, e.clientY);
+            // Changing which document to add the annotation to (the currently selected WebBox)
+            GPTPopup.Instance.setSidebarId(`${this.props.fieldKey}_${this._urlHash ? this._urlHash + '_' : ''}sidebar`);
+            GPTPopup.Instance.addDoc = this.sidebarAddDocument;
+        }
+    };
+    @action
     iframeDown = (e: PointerEvent) => {
         const mainContBounds = Utils.GetScreenTransform(this._mainCont.current!);
         const scale = (this.props.NativeDimScaling?.() || 1) * mainContBounds.scale;
@@ -396,9 +435,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             ContextMenu.Instance.setIgnoreEvents(true);
         }
     };
-    isFirefox = () => {
-        return 'InstallTrigger' in window; // navigator.userAgent.indexOf("Chrome") !== -1;
-    };
+    isFirefox = () => 'InstallTrigger' in window; // navigator.userAgent.indexOf("Chrome") !== -1;
     iframeClick = () => this._iframeClick;
     iframeScaling = () => 1 / this.props.ScreenToLocalTransform().Scale;
 
@@ -722,10 +759,11 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         }
     };
     @action finishMarquee = (x?: number, y?: number, e?: PointerEvent) => {
+        this._getAnchor = AnchorMenu.Instance?.GetAnchor;
         this._marqueeing = undefined;
         this._isAnnotating = false;
         this._iframeClick = undefined;
-        const sel = this._iframe?.contentDocument?.getSelection();
+        const sel = this._url ? this._iframe?.contentDocument?.getSelection() : window.document.getSelection();
         if (sel?.empty) sel.empty(); // Chrome
         else if (sel?.removeAllRanges) sel.removeAllRanges(); // Firefox
         if (x !== undefined && y !== undefined) {
@@ -750,7 +788,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         );
         const field = this.rootDoc[this.props.fieldKey];
         if (field instanceof HtmlField) {
-            return <span className="webBox-htmlSpan" contentEditable onPointerDown={e => e.stopPropagation()} dangerouslySetInnerHTML={{ __html: field.html }} />;
+            return <span className="webBox-htmlSpan" ref={r => r && (this._scrollHeight = Number(getComputedStyle(r).height.replace('px', '')))} contentEditable onPointerDown={this.webClipDown} dangerouslySetInnerHTML={{ __html: field.html }} />;
         }
         if (field instanceof WebField) {
             const url = this.layoutDoc[this.fieldKey + '_useCors'] ? Utils.CorsProxy(this._webUrl) : this._webUrl;
@@ -775,7 +813,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     }
 
     addDocumentWrapper = (doc: Doc | Doc[], annotationKey?: string) => {
-        (doc instanceof Doc ? [doc] : doc).forEach(doc => (doc.config_data = new WebField(this._url)));
+        this._url && (doc instanceof Doc ? [doc] : doc).forEach(doc => (doc.config_data = new WebField(this._url)));
         return this.addDocument(doc, annotationKey);
     };
 
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 2a3b232bd..383b400c8 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -465,7 +465,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             const fkey = Doc.LayoutFieldKey(bestTarget);
             const setData = bestTargetView?.ComponentView?.setData;
             if (setData) setData(activeItem.config_data);
-            else Doc.GetProto(bestTarget)[fkey] = activeItem.config_data instanceof ObjectField ? activeItem.config_data[Copy]() : activeItem.config_data;
+            else {
+                const current = Doc.GetProto(bestTarget)[fkey];
+                Doc.GetProto(bestTarget)[fkey + '_' + Date.now()] = current instanceof ObjectField ? current[Copy]() : current;
+                Doc.GetProto(bestTarget)[fkey] = activeItem.config_data instanceof ObjectField ? activeItem.config_data[Copy]() : activeItem.config_data;
+            }
             bestTarget[fkey + '_usePath'] = activeItem.config_usePath;
             setTimeout(() => (bestTarget._dataTransition = undefined), transTime + 10);
         }
@@ -2650,7 +2654,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 removeDocument={returnFalse}
                                 dontRegisterView={true}
                                 focus={this.focusElement}
-                                scriptContext={this}
                                 ScreenToLocalTransform={this.getTransform}
                                 AddToMap={this.AddToMap}
                                 RemFromMap={this.RemFromMap}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 2a191477b..23dc084ad 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -82,9 +82,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
     private _ignoreScroll = false;
     private _initialScroll: { loc: Opt<number>; easeFunc: 'linear' | 'ease' | undefined } | undefined;
     private _forcedScroll = true;
-    get _getAnchor() {
-        return AnchorMenu.Instance?.GetAnchor;
-    }
+    _getAnchor: (savedAnnotations: Opt<ObservableMap<number, HTMLDivElement[]>>, addAsAnnotation: boolean) => Opt<Doc> = () => undefined;
 
     selectionText = () => this._selectionText;
     selectionContent = () => this._selectionContent;
@@ -400,6 +398,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
 
     @action
     finishMarquee = (x?: number, y?: number) => {
+        this._getAnchor = AnchorMenu.Instance?.GetAnchor;
         this.isAnnotating = false;
         this._marqueeing = undefined;
         this._textSelecting = true;
-- 
cgit v1.2.3-70-g09d2

