From 0bd7f4f85be56de4326f0671453fc5e5e917a5d0 Mon Sep 17 00:00:00 2001
From: Lionel Han <47760119+IGoByJoe@users.noreply.github.com>
Date: Sun, 7 Jun 2020 21:22:25 -0700
Subject: pull current work in

---
 src/client/views/GestureOverlay.tsx | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

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

diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 4352ac52c..a11c97b09 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -27,7 +27,7 @@ import { listSpec } from "../../fields/Schema";
 import { List } from "../../fields/List";
 import { CollectionViewType } from "./collections/CollectionView";
 import TouchScrollableMenu, { TouchScrollableMenuItem } from "./TouchScrollableMenu";
-import MobileInterface from "../../mobile/MobileInterface";
+import { MobileInterface } from "../../mobile/MobileInterface";
 import { MobileInkOverlayContent } from "../../server/Message";
 import MobileInkOverlay from "../../mobile/MobileInkOverlay";
 import { RadialMenu } from "./nodes/RadialMenu";
@@ -115,12 +115,12 @@ export default class GestureOverlay extends Touchable {
     onReactTouchStart = (te: React.TouchEvent) => {
         document.removeEventListener("touchmove", this.onReactHoldTouchMove);
         document.removeEventListener("touchend", this.onReactHoldTouchEnd);
-        if (RadialMenu.Instance._display === true) {
-            te.preventDefault();
-            te.stopPropagation();
-            RadialMenu.Instance.closeMenu();
-            return;
-        }
+        // if (RadialMenu.Instance._display === true) {
+        //     te.preventDefault();
+        //     te.stopPropagation();
+        //     RadialMenu.Instance.closeMenu();
+        //     return;
+        // }
 
         // this chunk adds new touch targets to a map of pointer events; this helps us keep track of individual fingers
         // so that we can know, for example, if two fingers are pinching out or in.
-- 
cgit v1.2.3-70-g09d2


From 2f1714f0175f8fc766ba030848f5469e429307f4 Mon Sep 17 00:00:00 2001
From: geireann <60007097+geireann@users.noreply.github.com>
Date: Fri, 12 Jun 2020 11:17:40 +0800
Subject: menu bug fix

---
 src/client/views/GestureOverlay.tsx  |    2 +-
 src/client/views/nodes/AudioBox.scss |  206 +++++--
 src/client/views/nodes/ColorBox.tsx  |    4 +-
 src/mobile/MobileInterface.tsx       | 1012 ++--------------------------------
 src/mobile/MobileMenu.scss           |    5 +-
 5 files changed, 192 insertions(+), 1037 deletions(-)

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

diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 1879f3096..3bb80abd0 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -107,7 +107,7 @@ export default class GestureOverlay extends Touchable {
     onReactTouchStart = (te: React.TouchEvent) => {
         document.removeEventListener("touchmove", this.onReactHoldTouchMove);
         document.removeEventListener("touchend", this.onReactHoldTouchEnd);
-        if (RadialMenu.Instance._display === true) {
+        if (RadialMenu.Instance?._display === true) {
             te.preventDefault();
             te.stopPropagation();
             RadialMenu.Instance.closeMenu();
diff --git a/src/client/views/nodes/AudioBox.scss b/src/client/views/nodes/AudioBox.scss
index 53b54d7e4..61ce4bd13 100644
--- a/src/client/views/nodes/AudioBox.scss
+++ b/src/client/views/nodes/AudioBox.scss
@@ -1,141 +1,169 @@
-.audiobox-container, .audiobox-container-interactive {
+.audiobox-container,
+.audiobox-container-interactive {
     width: 100%;
     height: 100%;
     position: inherit;
-    display:flex;
+    display: flex;
     pointer-events: all;
-    cursor:default;
+    cursor: default;
+
     .audiobox-buttons {
         display: flex;
         width: 100%;
         align-items: center;
     }
+
     .audiobox-handle {
-        width:20px;
-        height:100%;
-        display:inline-block;
+        width: 20px;
+        height: 100%;
+        display: inline-block;
     }
-    .audiobox-control, .audiobox-control-interactive {
-        top:0;
+
+    .audiobox-control,
+    .audiobox-control-interactive {
+        top: 0;
         max-height: 32px;
         width: 100%;
-        display:inline-block;
+        display: inline-block;
         pointer-events: none;
     }
+
     .audiobox-control-interactive {
         pointer-events: all;
     }
+
     .audiobox-record {
         pointer-events: all;
-        width:100%;
-        height:100%;
+        width: 100%;
+        height: 100%;
         position: relative;
         pointer-events: none;
     }
+
     .audiobox-record-interactive {
         pointer-events: all;
-        width:100%;
-        height:100%;
+        width: 100%;
+        height: 100%;
         position: relative;
     }
+
     .audiobox-controls {
-        width:100%;
-        height:100%;
+        width: 100%;
+        height: 100%;
         position: relative;
         display: flex;
         padding-left: 2px;
+
         .audiobox-player {
-            margin-top:auto;
-            margin-bottom:auto;
-            width:100%;
+            margin-top: auto;
+            margin-bottom: auto;
+            width: 100%;
             height: 80%;
             position: relative;
             padding-right: 5px;
             display: flex;
-            .audiobox-playhead, .audiobox-dictation {
+
+            .audiobox-playhead,
+            .audiobox-dictation {
                 position: relative;
                 margin-top: auto;
                 margin-bottom: auto;
                 width: 25px;
                 padding: 2px;
             }
+
             .audiobox-dictation {
                 align-items: center;
                 display: inherit;
                 background: dimgray;
             }
+
             .audiobox-timeline {
-                position:relative;
-                height:100%;
-                width:100%;
+                position: relative;
+                height: 100%;
+                width: 100%;
                 background: white;
                 border: gray solid 1px;
                 border-radius: 3px;
+
                 .audiobox-current {
                     width: 1px;
-                    height:100%;
+                    height: 100%;
                     background-color: red;
                     position: absolute;
                 }
-                .audiobox-linker, .audiobox-linker-mini {
-                    position:absolute;
-                    width:15px;
-                    min-height:10px;
-                    height:15px;
-                    margin-left:-2.55px;
-                    background:gray;
+
+                .audiobox-linker,
+                .audiobox-linker-mini {
+                    position: absolute;
+                    width: 15px;
+                    min-height: 10px;
+                    height: 15px;
+                    margin-left: -2.55px;
+                    background: gray;
                     border-radius: 100%;
-                    opacity:0.9;
+                    opacity: 0.9;
                     background-color: transparent;
                     box-shadow: black 2px 2px 1px;
+
                     .linkAnchorBox-cont {
                         position: relative !important;
-                        height: 100%  !important;
+                        height: 100% !important;
                         width: 100% !important;
-                        left:unset !important;
-                        top:unset !important;
+                        left: unset !important;
+                        top: unset !important;
                     }
                 }
+
                 .audiobox-linker-mini {
-                    width:8px;
-                    min-height:8px;
-                    height:8px;
+                    width: 8px;
+                    min-height: 8px;
+                    height: 8px;
                     box-shadow: black 1px 1px 1px;
                     margin-left: -1;
                     margin-top: -2;
+
                     .linkAnchorBox-cont {
                         position: relative !important;
-                        height: 100%  !important;
+                        height: 100% !important;
                         width: 100% !important;
-                        left:unset !important;
-                        top:unset !important;
+                        left: unset !important;
+                        top: unset !important;
                     }
                 }
-                .audiobox-linker:hover, .audiobox-linker-mini:hover {
-                    opacity:1;
+
+                .audiobox-linker:hover,
+                .audiobox-linker-mini:hover {
+                    opacity: 1;
                 }
-                .audiobox-marker-container, .audiobox-marker-minicontainer {
-                    position:absolute;
-                    width:10px;
-                    height:90%;
-                    top:2.5%;
-                    background:gray;
+
+                .audiobox-marker-container,
+                .audiobox-marker-minicontainer {
+                    position: absolute;
+                    width: 10px;
+                    height: 90%;
+                    top: 2.5%;
+                    background: gray;
                     border-radius: 5px;
                     box-shadow: black 2px 2px 1px;
+
                     .audiobox-marker {
-                        position:relative;
+                        position: relative;
                         height: calc(100% - 15px);
                         margin-top: 15px;
                     }
+
                     .audio-marker:hover {
                         border: orange 2px solid;
                     }
                 }
+
                 .audiobox-marker-minicontainer {
-                    width:5px;
+                    width: 5px;
                     border-radius: 1px;
+
                     .audiobox-marker {
-                        position:relative;
+                        position: relative;
                         height: calc(100% - 8px);
                         margin-top: 8px;
                     }
@@ -143,4 +171,80 @@
             }
         }
     }
+}
+
+
+@media only screen and (max-width: 1000px) {
+
+    .audiobox-container,
+    .audiobox-container-interactive {
+        width: max-content;
+        /* align-self: center; */
+        left: 50%;
+        top: 40%;
+        transform: translate(-50%, 0);
+        height: 100px;
+        position: absolute;
+        display: flex;
+        pointer-events: all;
+        /* cursor: default; */
+    }
+
+    .audiobox-container .audiobox-buttons,
+    .audiobox-container-interactive .audiobox-buttons {
+        display: flex;
+        width: 500px;
+        /* left: 50%; */
+        /* transform: translate(-50%,0); */
+        align-items: center;
+    }
+
+    .audiobox-dictation {
+        width: 100;
+        height: 100;
+        font-size: 50;
+        /* background-color: white; */
+    }
+
+    .audiobox-container .audiobox-record-interactive,
+    .audiobox-container-interactive .audiobox-record-interactive {
+        width: 95%;
+        user-select: none;
+        font-size: 50px;
+        font-weight: 100;
+        left: 5%;
+        height: 100%;
+        position: relative;
+    }
+
+    .audiobox-container .audiobox-controls .audiobox-player .audiobox-playhead,
+    .audiobox-container .audiobox-controls .audiobox-player .audiobox-dictation,
+    .audiobox-container-interactive .audiobox-controls .audiobox-player .audiobox-playhead,
+    .audiobox-container-interactive .audiobox-controls .audiobox-player .audiobox-dictation {
+        position: relative;
+        align-self: center;
+        width: 50px;
+        height: max-content;
+        padding: 0;
+    }
+
+    .audiobox-container .audiobox-controls .audiobox-player,
+    .audiobox-container-interactive .audiobox-controls .audiobox-player {
+        margin-top: auto;
+        margin-bottom: auto;
+        width: 100%;
+        height: 100%;
+        position: relative;
+        padding-right: 5px;
+        display: flex;
+    }
+
+    .audiobox-container .audiobox-controls,
+    .audiobox-container-interactive .audiobox-controls {
+        width: 500px;
+        height: 100%;
+        position: relative;
+        display: flex;
+        padding-left: 2px;
+    }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/ColorBox.tsx b/src/client/views/nodes/ColorBox.tsx
index 0d6258cf3..f49b1f763 100644
--- a/src/client/views/nodes/ColorBox.tsx
+++ b/src/client/views/nodes/ColorBox.tsx
@@ -60,9 +60,9 @@ export class ColorBox extends ViewBoxBaseComponent<FieldViewProps, ColorDocument
                     StrCast(selDoc?._backgroundColor, StrCast(selDoc?.backgroundColor, "black")))} />
             <div style={{ display: "grid", gridTemplateColumns: "20% 80%", paddingTop: "10px" }}>
                 <div> {ActiveInkWidth() ?? 2}</div>
-                <input type="range" value={ActiveInkWidth() ?? 2} defaultValue={2} min={1} max={100} onChange={(e: React.ChangeEvent<HTMLInputElement>) => SetActiveInkWidth(e.target.value)} />
+                <input type="range" value={ActiveInkWidth() ?? 2} min={1} max={100} onChange={(e: React.ChangeEvent<HTMLInputElement>) => SetActiveInkWidth(e.target.value)} />
                 <div> {ActiveInkBezierApprox() ?? 2}</div>
-                <input type="range" value={ActiveInkBezierApprox() ?? 2} defaultValue={2} min={0} max={300} onChange={(e: React.ChangeEvent<HTMLInputElement>) => SetActiveBezierApprox(e.target.value)} />
+                <input type="range" value={ActiveInkBezierApprox() ?? 2} min={0} max={300} onChange={(e: React.ChangeEvent<HTMLInputElement>) => SetActiveBezierApprox(e.target.value)} />
                 <br />
                 <br />
             </div>
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index d9399d549..687422cf2 100644
--- a/src/mobile/MobileInterface.tsx
+++ b/src/mobile/MobileInterface.tsx
@@ -46,903 +46,6 @@ library.add(faTasks, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faP
     faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote,
     faThumbtack, faTree, faTv, faUndoAlt, faBook, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faHome, faLongArrowAltLeft, faBars, faTh, faChevronLeft);
 
-// @observer
-// export class MobileInterface extends React.Component {
-//     @observable static Instance: MobileInterface;
-//     @computed private get userDoc() { return Doc.UserDoc(); }
-//     @computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeMobile, Doc)) : CurrentUserUtils.GuestMobile; }
-//     @computed private get activeContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeMobile, Doc)) : CurrentUserUtils.GuestMobile; }
-//     // @observable private currentView: "main" | "ink" | "upload" = "main";
-//     @observable private mainDoc: any = CurrentUserUtils.setupMobileDoc(this.userDoc);
-//     @observable private renderView?: () => JSX.Element;
-//     @observable private sidebarActive = true;
-
-//     public _activeDoc: Doc = this.mainDoc;
-//     public _homeDoc: Doc = this.mainDoc;
-//     private _homeMenu: boolean = true;
-
-//     // private inkDoc?: Doc;
-//     public drawingInk: boolean = false;
-//     private _ink: boolean = false;
-
-//     // private _uploadDoc: Doc = this.userDoc;
-//     private _child: Doc | null = null;
-//     private _parents: Array<Doc> = [];
-//     private _library: Doc = CurrentUserUtils.setupLibrary(this.userDoc);
-//     private _open: boolean = false;
-
-//     constructor(props: Readonly<{}>) {
-//         super(props);
-//         MobileInterface.Instance = this;
-//     }
-
-//     @action
-//     componentDidMount = () => {
-//         library.add(...[faPenNib, faHighlighter, faEraser, faMousePointer, faThumbtack]);
-
-//         if (this.userDoc && !this.mainContainer) {
-//             this.userDoc.activeMobile = this._homeDoc;
-//         }
-
-//         InkingControl.Instance.switchTool(InkTool.None);
-//         MobileInterface.Instance.drawingInk = false;
-//         InkingControl.Instance.updateSelectedColor("#FF0000");
-//         InkingControl.Instance.switchWidth("2");
-//         this.switchCurrentView((userDoc: Doc) => this._homeDoc);
-//     }
-
-//     @action
-//     switchCurrentView = (doc: (userDoc: Doc) => Doc, renderView?: () => JSX.Element, onSwitch?: () => void) => {
-//         if (!this.userDoc) return;
-
-//         this.userDoc.activeMobile = doc(this.userDoc);
-//         onSwitch && onSwitch();
-
-//         this.renderView = renderView;
-//     }
-
-//     onSwitchInking = () => {
-//         const button = document.getElementById("inkButton") as HTMLElement;
-//         const color = InkingControl.Instance.selectedColor;
-//         button.style.backgroundColor = this._ink ? "white" : color;
-//         button.style.color = this._ink ? "black" : "white";
-
-//         if (!this._ink) {
-//             console.log("INK IS ACTIVE");
-//             InkingControl.Instance.switchTool(InkTool.Pen);
-//             MobileInterface.Instance.drawingInk = true;
-//             this._ink = true;
-//         } else {
-//             console.log("INK IS INACTIVE");
-//             InkingControl.Instance.switchTool(InkTool.None);
-//             MobileInterface.Instance.drawingInk = false;
-//             this._ink = false;
-//         }
-//     }
-
-//     onSwitchUpload = async () => {
-//         let width = 300;
-//         let height = 300;
-//         const res = await rp.get(Utils.prepend("/getUserDocumentId"));
-
-//         // get width and height of the collection doc
-//         if (this.mainContainer) {
-//             const data = Cast(this.mainContainer.data, listSpec(Doc));
-//             if (data) {
-//                 const collectionDoc = await data[1]; // this should be the collection doc since the positions should be locked
-//                 const docView = DocumentManager.Instance.getDocumentView(collectionDoc);
-//                 if (docView) {
-//                     width = docView.nativeWidth ? docView.nativeWidth : 300;
-//                     height = docView.nativeHeight ? docView.nativeHeight : 300;
-//                 }
-//             }
-//         }
-//         DocServer.Mobile.dispatchOverlayTrigger({
-//             enableOverlay: true,
-//             width: width,
-//             height: height,
-//             text: "Documents uploaded from mobile will show here",
-//         });
-//     }
-
-//     back = () => {
-//         let header = document.getElementById("header") as HTMLElement;
-//         let doc = Cast(this._parents.pop(), Doc) as Doc;
-//         if (doc === Cast(this._library, Doc) as Doc) {
-//             this._child = null;
-//             this.userDoc.activeMobile = this._library;
-//         } else if (doc === Cast(this._homeDoc, Doc) as Doc) {
-//             this._homeMenu = true;
-//             this._parents = [];
-//             this._activeDoc = this._homeDoc;
-//             this._child = null;
-//             this.switchCurrentView((userDoc: Doc) => this._homeDoc);
-//         } else {
-//             if (doc) {
-//                 this._child = doc;
-//                 this.switchCurrentView((userDoc: Doc) => doc);
-//                 this._homeMenu = false;
-//                 header.textContent = String(doc.title);
-//             }
-//         }
-//         if (doc) {
-//             this._activeDoc = doc;
-//         }
-//         this._ink = false;
-//     }
-
-//     returnHome = () => {
-//         if (this._homeMenu === false || this._open === true) {
-//             this._homeMenu = true;
-//             this._parents = [];
-//             this._activeDoc = this._homeDoc;
-//             this._child = null;
-//             this.switchCurrentView((userDoc: Doc) => this._homeDoc);
-//         }
-//         if (this._open) {
-//             this.toggleSidebar();
-//         }
-//     }
-
-//     returnMain = () => {
-//         this._parents = [];
-//         // this.toggleSidebar();
-//         this._activeDoc = this._library;
-//         this.switchCurrentView((userDoc: Doc) => this._library);
-//         this._homeMenu = false;
-//         this._child = null;
-//     }
-
-//     displayWorkspaces = () => {
-//         if (this.mainContainer) {
-//             const backgroundColor = () => "white";
-//             if (this._activeDoc.title === "mobile audio") {
-//                 return (
-//                     <div style={{ position: "relative", top: '600px', height: `calc(50% - 450px)`, width: "80%", overflow: "hidden", left: "10%", cursor: "pointer" }}>
-//                         <DocumentView
-//                             Document={this.mainContainer}
-//                             DataDoc={undefined}
-//                             LibraryPath={emptyPath}
-//                             addDocument={returnFalse}
-//                             addDocTab={returnFalse}
-//                             pinToPres={emptyFunction}
-//                             rootSelected={returnFalse}
-//                             removeDocument={undefined}
-//                             onClick={undefined}
-//                             ScreenToLocalTransform={Transform.Identity}
-//                             ContentScaling={returnOne}
-//                             NativeHeight={returnZero}
-//                             NativeWidth={returnZero}
-//                             PanelWidth={() => window.screen.width}
-//                             PanelHeight={() => window.screen.height}
-//                             renderDepth={0}
-//                             focus={emptyFunction}
-//                             backgroundColor={backgroundColor}
-//                             parentActive={returnTrue}
-//                             whenActiveChanged={emptyFunction}
-//                             bringToFront={emptyFunction}
-//                             ContainingCollectionView={undefined}
-//                             ContainingCollectionDoc={undefined}
-//                         />
-//                     </div>
-//                 );
-//             } else {
-//                 return (
-//                     <div style={{ position: "relative", top: '200px', height: `calc(100% - 200px)`, width: "100%", overflow: "hidden", left: "0%" }}>
-//                         <DocumentView
-//                             Document={this.mainContainer}
-//                             DataDoc={undefined}
-//                             LibraryPath={emptyPath}
-//                             addDocument={returnFalse}
-//                             addDocTab={returnFalse}
-//                             pinToPres={emptyFunction}
-//                             rootSelected={returnFalse}
-//                             removeDocument={undefined}
-//                             onClick={undefined}
-//                             ScreenToLocalTransform={Transform.Identity}
-//                             ContentScaling={returnOne}
-//                             PanelWidth={this.returnWidth}
-//                             PanelHeight={this.returnHeight}
-//                             NativeHeight={returnZero}
-//                             NativeWidth={returnZero}
-//                             renderDepth={0}
-//                             focus={emptyFunction}
-//                             backgroundColor={backgroundColor}
-//                             parentActive={returnTrue}
-//                             whenActiveChanged={emptyFunction}
-//                             bringToFront={emptyFunction}
-//                             ContainingCollectionView={undefined}
-//                             ContainingCollectionDoc={undefined}
-//                         // mobile={true}
-//                         />
-//                     </div>
-//                 );
-//             }
-//         }
-//     }
-
-//     returnWidth = () => 2000;
-//     returnHeight = () => 2000;
-
-//     handleClick(doc: Doc) {
-//         let children = DocListCast(doc.data);
-//         if (doc.type !== "collection") {
-//             this._parents.push(this._activeDoc);
-//             this._activeDoc = doc;
-//             this.switchCurrentView((userDoc: Doc) => doc);
-//             this._homeMenu = false;
-//             this.toggleSidebar();
-//         } else if (doc.type === "collection" && children.length === 0) {
-//             console.log("This collection has no children");
-//         } else {
-//             this._parents.push(this._activeDoc);
-//             this._activeDoc = doc;
-//             this.switchCurrentView((userDoc: Doc) => doc);
-//             this._homeMenu = false;
-//             this._child = doc;
-//         }
-
-//         // let sidebar = document.getElementById("sidebar") as HTMLElement;
-//         // sidebar.classList.toggle('active');
-//     }
-
-//     createPathname = () => {
-//         let docArray = [];
-//         this._parents.map((doc: Doc, index: any) => {
-//             // if (doc === this.mainDoc) {
-//             //     pathname = pathname;
-//             // } else if (doc.type === "audio" || doc.type === "presentation") {
-//             //     pathname = pathname;
-//             // } else if (doc.type !== "collection") {
-//             //     pathname = pathname;
-//             // } else {
-//             //     pathname = pathname + " > " + doc.title;
-//             //     titleArray.push(doc.title);
-//             //     docArray.push(doc);
-//             // }
-//             docArray.push(doc);
-//         });
-//         docArray.push(this._activeDoc);
-//         // if (this._activeDoc.title === "mobile audio") {
-//         //     pathname = this._activeDoc.title;
-//         // } else if (this._activeDoc.title === "Presentation") {
-//         //     pathname = this._activeDoc.title;
-//         // } else if (this._activeDoc === this.mainDoc) {
-//         //     pathname = pathname;
-//         // } else {
-//         //     pathname = pathname + " > " + this._activeDoc.title;
-//         //     docArray.push(this._activeDoc);
-//         //     titleArray.push(this._activeDoc.title);
-//         // }
-
-//         return docArray;
-//     }
-
-//     renderPathbar = () => {
-//         // if (this._homeMenu == false) {
-//         let docArray = this.createPathname();
-//         let items = docArray.map((doc: Doc, index: any) => {
-//             if (index == 0) {
-//                 return (
-//                     <div className="pathbarItem">
-//                         <div className="pathbarText"
-//                             key={index}
-//                             onClick={() => this.handlePathClick(doc, index)}>{doc.title}
-//                         </div>
-//                     </div>);
-//             } else if (doc === this._activeDoc) {
-//                 return (
-//                     <div className="pathbarItem">
-//                         <FontAwesomeIcon className="pathIcon" icon="angle-right" size="lg" />
-//                         <div className="pathbarText"
-//                             style={{ backgroundColor: "rgb(119, 37, 37)" }}
-//                             key={index}
-//                             onClick={() => this.handlePathClick(doc, index)}>{doc.title}
-//                         </div>
-//                     </div>);
-//             } else {
-//                 return (
-//                     <div className="pathbarItem">
-//                         <FontAwesomeIcon className="pathIcon" icon="angle-right" size="lg" />
-//                         <div className="pathbarText"
-//                             key={index}
-//                             onClick={() => this.handlePathClick(doc, index)}>{doc.title}
-//                         </div>
-//                     </div>);
-//             }
-
-//         });
-//         if (this._parents.length !== 0) {
-//             return (<div className="pathbar">
-//                 <div className="scrollmenu">
-//                     {items}
-//                 </div>
-//                 <div className="back" >
-//                     <FontAwesomeIcon onClick={this.back} icon={"chevron-left"} color="white" size={"2x"} />
-//                 </div>
-//                 <div className="hidePath" />
-//             </div>);
-//         } else {
-//             return (<div className="pathbar">
-//                 <div className="scrollmenu">
-//                     {items}
-//                 </div>
-//                 <div className="hidePath" />
-//             </div>);
-//         }
-//         //     }
-//         // } else {
-
-//         //     return (
-//         //         <div className="pathbar">
-//         //             <div className="scrollmenu">
-//         //                 <div className="pathbarItem">
-//         //                     <div className="pathbarText"
-//         //                         style={{ backgroundColor: "rgb(119, 37, 37)" }}
-//         //                         key={0}
-//         //                         onClick={() => this.returnHome()}>Home
-//         //                     </div>
-//         //                 </div>
-//         //             </div>
-//         //             <div className="hidePath" />
-//         //         </div>
-//         //     );
-//         // }
-
-//         // }
-//     }
-
-//     handlePathClick = (doc: Doc, index: number) => {
-//         if (doc === this._library) {
-//             this._activeDoc = doc;
-//             this._child = null;
-//             this.switchCurrentView((userDoc: Doc) => doc);
-//             this._parents.length = index;
-//         } else if (doc === this._homeDoc) {
-//             this.returnHome();
-//         } else {
-//             console.log(index);
-//             this._activeDoc = doc;
-//             this._child = doc;
-//             this.switchCurrentView((userDoc: Doc) => doc);
-//             this._parents.length = index;
-//         }
-//     }
-
-//     @action
-//     toggleSidebar = () => this.sidebarActive = !this.sidebarActive
-
-//     switchToLibrary = () => {
-//         this._parents.push(this._activeDoc);
-//         this.switchCurrentView((userDoc: Doc) => this._library);
-//         this._activeDoc = this._library;
-//         this._homeMenu = false;
-//         this.toggleSidebar();
-//     }
-
-//     // renderDefaultContent = () => {
-//     //     let menuButtons = DocListCast(this._homeDoc.data).map((doc: Doc, index: any) => {
-//     //         if (doc.type !== "ink") {
-//     //             return (
-//     //                 <div
-//     //                     className="item"
-//     //                     key={index}
-//     //                     onClick={() => doc.click}>{doc.title}
-//     //                 </div>);
-//     //         }
-//     //     });
-
-//     //     if (this._homeMenu === true) {
-//     //         return (
-//     //             <div>
-//     //                 <div className="navbar">
-//     //                     <FontAwesomeIcon className="home" icon="home" onClick={this.returnHome} />
-//     //                     <div className="header" id="header">{this._homeDoc.title}</div>
-//     //                     <div className="toggle-btn" id="menuButton" onClick={this.toggleSidebar}>
-//     //                         <span></span>
-//     //                         <span></span>
-//     //                         <span></span>
-//     //                     </div>
-//     //                 </div>
-//     //                 {this.renderPathbar()}
-//     //                 <div className="sidebar" id="sidebar">
-//     //                     <div className="sidebarButtons">
-//     //                         {menuButtons}
-//     //                     </div>
-//     //                 </div>
-//     //             </div>
-//     //         );
-//     //     }
-
-//     //     const workspaces = Cast(this.userDoc.myWorkspaces, Doc) as Doc;
-//     //     const buttons = DocListCast(this._child ? this._child.data : workspaces.data).map((doc: Doc, index: any) => {
-//     //         return (
-//     //             <div
-//     //                 className="item"
-//     //                 key={index}
-//     //                 onClick={() => this.handleClick(doc)}>{doc.title}
-//     //                 <div className="type">{doc.type}</div>
-//     //                 <FontAwesomeIcon className="right" icon="angle-right" size="lg" />
-//     //             </div>);
-//     //     });
-//     //     return (
-//     //         <>
-//     //             <div className="navbar">
-//     //                 <div className={"header"}>{this.sidebarActive ? StrCast(this._activeDoc.title) : "Menu"}</div>
-//     //                 <div
-//     //                     className={`toggle-btn ${this.sidebarActive ? "active" : ""}`}
-//     //                     onClick={this.toggleSidebar}
-//     //                 />
-//     //             </div>
-//     //             <div className="pathbar">
-//     //                 <div className="pathname">{this.createPathname()}</div>
-//     //             </div>
-//     //             <div className={`sidebar ${this.sidebarActive ? "active" : ""}`}>
-//     //                 <FontAwesomeIcon className="home" icon="home" onClick={this.returnHome} />
-//     //                 {this._child ?
-//     //                     <>
-//     //                         <div className="back" onClick={this.back}>&#8592;</div>
-//     //                         <div>{buttons}</div>
-//     //                         <div className="item" key="home" onClick={this.returnHome}>Home</div>
-//     //                     </> :
-//     //                     <>
-//     //                         {buttons}
-//     //                         {/* <div className="item" key="library" onClick={this.openLibrary}>
-//     //                             Library
-//     //                             </div> */}
-//     //                         <Uploader Document={workspaces} />
-//     //                         <div className="item" key="audio" onClick={this.recordAudio}>Record Audio</div>
-//     //                         <div className="item" key="presentation" onClick={this.setupDefaultPresentation}>Presentation</div>
-//     //                         <div className="item" key="settings" onClick={() => SettingsManager.Instance.open()}>Settings</div>
-//     //                     </>
-//     //                 }
-//     //             </div>
-//     //             {this._child ? null : <div>{this.renderView}</div>}
-//     //         </>
-//     //     );
-//     // }
-
-//     recordAudio = async () => {
-//         // upload to server with known URL
-//         if (this._activeDoc.title !== "mobile audio") {
-//             this._parents.push(this._activeDoc);
-//         }
-//         const audioDoc = Cast(Docs.Create.AudioDocument(nullAudio, { _width: 200, _height: 100, title: "mobile audio" }), Doc) as Doc;
-//         console.log(audioDoc);
-//         if (audioDoc) {
-//             console.log("audioClicked: " + audioDoc.title);
-//             this._activeDoc = audioDoc;
-//             this.switchCurrentView((userDoc: Doc) => audioDoc);
-//             this._homeMenu = false;
-//             // this.toggleSidebar();
-//         }
-//         // const audioRightSidebar = Cast(Doc.UserDoc().rightSidebarCollection, Doc) as Doc;
-//         // this.audioState = await audioDoc.getProto;
-//         // if (this.audioState) {
-//         //     console.log(this.audioState);
-//         //     const data = Cast(audioRightSidebar.data, listSpec(Doc));
-//         //     if (data) {
-//         //         data.push(audioDoc);
-//         //     }
-//         // }
-//     }
-
-//     uploadAudio = () => {
-//         const audioRightSidebar = Cast(Doc.UserDoc().rightSidebarCollection, Doc) as Doc;
-//         const audioDoc = this._activeDoc;
-//         const data = Cast(audioRightSidebar.data, listSpec(Doc));
-//         console.log(audioDoc.proto);
-//         if (data) {
-//             data.push(audioDoc);
-//         }
-//         // this.recordAudio();
-//     }
-
-//     uploadAudioButton = () => {
-//         if (this._activeDoc.type === "audio") {
-//             return <div className="docButton"
-//                 title={Doc.isDocPinned(this._activeDoc) ? "Pen on" : "Pen off"}
-//                 style={{ backgroundColor: "black", color: "white" }}
-//                 onClick={this.uploadAudio}
-//             >
-//                 <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="upload"
-//                 />
-//             </div>;
-//         }
-//     }
-
-//     toggleSelector = () => {
-//         console.log("toggle selector!");
-//         let toolbar = document.getElementById("toolbar") as HTMLElement;
-//         toolbar.classList.toggle('active');
-//     }
-
-//     colorTool = () => {
-//         if (this._activeDoc._viewType === "docking") {
-//             const color = InkingControl.Instance.selectedColor;
-//             console.log(color);
-//             return (
-//                 <div
-//                     className="docButton"
-//                     style={{ backgroundColor: color }}
-//                     onClick={this.toggleSelector}
-//                 >
-//                     <div className="toolbar" id="toolbar">
-//                         <div className="colorSelector">
-//                             <div className="colorButton"
-//                                 style={{ backgroundColor: "red" }}
-//                                 onClick={() => {
-//                                     InkingControl.Instance.updateSelectedColor("rgb(255,0,0)");
-//                                     Doc.UserDoc().inkColor = "rgb(255,0,0)";
-//                                     console.log(InkingControl.Instance.selectedColor);
-//                                 }}>
-//                             </div>
-//                             <div className="colorButton"
-//                                 style={{ backgroundColor: "green" }}
-//                                 onClick={e => {
-//                                     InkingControl.Instance.updateSelectedColor("rgb(0,128,0)");
-//                                     Doc.UserDoc().inkColor = "rgb(0,128,0)";
-//                                     console.log(InkingControl.Instance.selectedColor);
-//                                 }}>
-//                             </div>
-//                             <div className="colorButton"
-//                                 style={{ backgroundColor: "blue" }}
-//                                 onClick={e => {
-//                                     InkingControl.Instance.updateSelectedColor("rgb(0,0,255)");
-//                                     Doc.UserDoc().inkColor = "rgb(0,0,255)";
-//                                     console.log(InkingControl.Instance.selectedColor);
-//                                 }}>
-//                             </div>
-//                         </div>
-//                         <div className="widthSelector">
-//                             <input type="range" min="1" max="100" defaultValue="2" id="myRange" onChange={(e: React.ChangeEvent<HTMLInputElement>) => InkingControl.Instance.switchWidth(e.target.value)} />
-//                         </div>
-//                     </div>
-//                 </div>
-//             );
-//         }
-//     }
-
-//     drawInk = () => {
-//         if (this._activeDoc._viewType === "docking") {
-//             const inkIsOn = this._ink;
-//             return <div className="docButton"
-//                 id="inkButton"
-//                 title={Doc.isDocPinned(this._activeDoc) ? "Pen on" : "Pen off"}
-//                 onClick={this.onSwitchInking}>
-//                 <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="pen-nib"
-//                 />
-//             </div>;
-//         }
-//     }
-
-//     downloadDocument = () => {
-//         if (this._activeDoc.type === "image") {
-//             const url = this._activeDoc["data-path"]?.toString();
-//             return <div className="docButton"
-//                 title={"Download Image"}
-//                 style={{ backgroundColor: "white", color: "black" }}
-//                 onClick={e => {
-//                     window.open(url);
-//                     console.log(url);
-//                 }}>
-//                 <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="download"
-//                 />
-//             </div>;
-//         }
-//     }
-
-//     pinToPresentation = () => {
-//         // Only making button available if it is an image
-//         if (this._activeDoc.type === "image") {
-//             const isPinned = this._activeDoc && Doc.isDocPinned(this._activeDoc);
-//             return <div className="docButton"
-//                 title={Doc.isDocPinned(this._activeDoc) ? "Unpin from presentation" : "Pin to presentation"}
-//                 style={{ backgroundColor: isPinned ? "black" : "white", color: isPinned ? "white" : "black" }}
-//                 onClick={e => {
-//                     if (isPinned) {
-//                         DockedFrameRenderer.UnpinDoc(this._activeDoc);
-//                     }
-//                     else {
-//                         DockedFrameRenderer.PinDoc(this._activeDoc);
-//                     }
-//                 }}>
-//                 <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin"
-//                 />
-//             </div>;
-//         }
-//     }
-
-//     setupDefaultPresentation = () => {
-//         if (this._activeDoc.title !== "Presentation") {
-//             this._parents.push(this._activeDoc);
-//         }
-
-//         const presentation = Cast(Doc.UserDoc().activePresentation, Doc) as Doc;
-
-//         if (presentation) {
-//             console.log(this._activeDoc.mobile);
-//             console.log("presentation clicked: " + presentation.title);
-//             this._activeDoc = presentation;
-//             this.switchCurrentView((userDoc: Doc) => presentation);
-//             this._homeMenu = false;
-//             // this.toggleSidebar();
-//         }
-//     }
-
-//     // mobileHome = () => {
-//     //     return (
-//     //         <div className="homeContainer">
-//     //             <div className="uploadButton">
-
-//     //             </div>
-//     //             <div className="presentationButton">
-
-//     //             </div>
-//     //             <div className="recordAudioButton">
-
-//     //             </div>
-//     //             <div className="inkButton">
-
-//     //             </div>
-//     //             <div className="settingsButton">
-
-//     //             </div>
-//     //         </div>
-//     //     );
-//     // }
-
-//     renderActiveCollection = (userDoc: Doc) => {
-//         if (this.activeContainer) {
-//             const active = Cast(this.activeContainer.data, listSpec(Doc));
-//             if (active) {
-//                 return (
-//                     <div className="mobileInterface-background">HELLO!</div>
-//                 );
-//             }
-//         }
-//     }
-
-//     onBack = (e: React.MouseEvent) => {
-//         this.switchCurrentView((userDoc: Doc) => this.mainDoc);
-//         InkingControl.Instance.switchTool(InkTool.None); // TODO: switch to previous tool
-
-//         DocServer.Mobile.dispatchOverlayTrigger({
-//             enableOverlay: false,
-//             width: window.innerWidth,
-//             height: window.innerHeight
-//         });
-
-//         // this.inkDoc = undefined;
-//         this.drawingInk = false;
-//     }
-
-//     shiftLeft = (e: React.MouseEvent) => {
-//         DocServer.Mobile.dispatchOverlayPositionUpdate({
-//             dx: -10
-//         });
-//         e.preventDefault();
-//         e.stopPropagation();
-//     }
-
-//     shiftRight = (e: React.MouseEvent) => {
-//         DocServer.Mobile.dispatchOverlayPositionUpdate({
-//             dx: 10
-//         });
-//         e.preventDefault();
-//         e.stopPropagation();
-//     }
-
-//     panelHeight = () => window.innerHeight;
-//     panelWidth = () => window.innerWidth;
-//     //WAS 3
-
-//     //WAS 1
-
-//     upload = async (e: React.MouseEvent) => {
-//         if (this.mainContainer) {
-//             const data = Cast(this.mainContainer.data, listSpec(Doc));
-//             if (data) {
-//                 const collectionDoc = await data[1]; //this should be the collection doc since the positions should be locked
-//                 const children = DocListCast(collectionDoc.data);
-//                 const uploadDoc = children.length === 1 ? children[0] : Docs.Create.StackingDocument(children, {
-//                     title: "Mobile Upload Collection", backgroundColor: "white", lockedPosition: true, _width: 300, _height: 300
-//                 });
-//                 if (uploadDoc) {
-//                     DocServer.Mobile.dispatchMobileDocumentUpload({
-//                         docId: uploadDoc[Id],
-//                     });
-//                 }
-//             }
-//         }
-//         e.stopPropagation();
-//         e.preventDefault();
-//     }
-
-//     addWebToCollection = async () => {
-//         let url = "https://en.wikipedia.org/wiki/Hedgehog";
-//         if (this.mainContainer) {
-//             const data = Cast(this.mainContainer.data, listSpec(Doc));
-//             if (data) {
-//                 const webDoc = await data[0];
-//                 const urlField: FieldResult<WebField> = Cast(webDoc.data, WebField);
-//                 url = urlField ? urlField.url.toString() : "https://en.wikipedia.org/wiki/Hedgehog";
-
-//             }
-//         }
-//         Docs.Create.WebDocument(url, { _width: 300, _height: 300, title: "Mobile Upload Web Doc" });
-//     }
-
-//     clearUpload = async () => {
-//         if (this.mainContainer) {
-//             const data = Cast(this.mainContainer.data, listSpec(Doc));
-//             if (data) {
-//                 const collectionDoc = await data[1];
-//                 const children = DocListCast(collectionDoc.data);
-//                 children.forEach(doc => {
-//                 });
-//                 // collectionDoc[data] = new List<Doc>();
-//             }
-//         }
-//     }
-
-//     onDragOver = (e: React.DragEvent) => {
-//         e.preventDefault();
-//         e.stopPropagation();
-//     }
-
-//     render() {
-//         // const content = this.currentView === "main" ? this.mainContent :
-//         //     this.currentView === "ink" ? this.inkContent :
-//         //         this.currentView === "upload" ? this.uploadContent : <></>;
-//         return (
-//             <div className="mobileInterface-container" onDragOver={this.onDragOver}>
-//                 {/* <DocumentDecorations />
-//                 <GestureOverlay>
-//                     {this.renderView ? this.renderView() : this.renderDefaultContent()}
-//                 </GestureOverlay> */}
-//                 {/* <GestureOverlay> */}
-//                 <SettingsManager />
-//                 {/* {this.menuOptions()} */}
-//                 {/* {this.displayHome()} */}
-//                 <div className="docButtonContainer">
-//                     {this.pinToPresentation()}
-//                     {this.downloadDocument()}
-//                     {this.drawInk()}
-//                     {this.uploadAudioButton()}
-//                     {this.colorTool()}
-//                 </div>
-//                 <GestureOverlay>
-
-//                 </GestureOverlay>
-//                 {this.renderDefaultContent()}
-//                 {this.displayWorkspaces()}
-//                 {/* </GestureOverlay> */}
-//                 {/* <DictationOverlay />
-//                 <SharingManager />
-//                 <GoogleAuthenticationManager /> */}
-//                 {/* <DocumentDecorations /> */}
-//                 {/* <div>
-//                     {this.renderDefaultContent()}
-//                 </div> */}
-//                 {/* <PreviewCursor /> */}
-//                 {/* <ContextMenu /> */}
-//                 {/* <RadialMenu />
-//                 <RichTextMenu /> */}
-//                 {/* <PDFMenu />
-//                 <MarqueeOptionsMenu />
-//                 <OverlayView /> */}
-//             </div>
-//         );
-//     }
-// }
-
-// Scripting.addGlobal(function switchMobileView(doc: (userDoc: Doc) => Doc, renderView?: () => JSX.Element, onSwitch?: () => void) { return MobileInterface.Instance.switchCurrentView(doc, renderView, onSwitch); });
-// Scripting.addGlobal(function openMobilePresentation() { return MobileInterface.Instance.setupDefaultPresentation(); });
-// Scripting.addGlobal(function toggleMobileSidebar() { return MobileInterface.Instance.toggleSidebar(); });
-// Scripting.addGlobal(function openMobileAudio() { return MobileInterface.Instance.recordAudio(); });
-// Scripting.addGlobal(function openMobileSettings() { return SettingsManager.Instance.open(); });
-// Scripting.addGlobal(function switchToLibrary() { return MobileInterface.Instance.switchToLibrary(); });
-// // WAS 2
-
-// // 1
-// // renderUploadContent() {
-// //     if (this.mainContainer) {
-// //         return (
-// //             <div className="mobileInterface" onDragOver={this.onDragOver}>
-// //                 <div className="mobileInterface-inkInterfaceButtons">
-// //                     <button className="mobileInterface-button cancel" onClick={this.onBack} title="Back">BACK</button>
-// //                     {/* <button className="mobileInterface-button" onClick={this.clearUpload} title="Clear Upload">CLEAR</button> */}
-// //                     {/* <button className="mobileInterface-button" onClick={this.addWeb} title="Add Web Doc to Upload Collection"></button> */}
-// //                     <button className="mobileInterface-button" onClick={this.upload} title="Upload">UPLOAD</button>
-// //                 </div>
-// //                 <DocumentView
-// //                     Document={this.mainContainer}
-// //                     DataDoc={undefined}
-// //                     LibraryPath={emptyPath}
-// //                     addDocument={returnFalse}
-// //                     addDocTab={returnFalse}
-// //                     pinToPres={emptyFunction}
-// //                     rootSelected={returnFalse}
-// //                     removeDocument={undefined}
-// //                     onClick={undefined}
-// //                     ScreenToLocalTransform={Transform.Identity}
-// //                     ContentScaling={returnOne}
-// //                     NativeHeight={returnZero}
-// //                     NativeWidth={returnZero}
-// //                     PanelWidth={() => window.screen.width}
-// //                     PanelHeight={() => window.screen.height}
-// //                     renderDepth={0}
-// //                     focus={emptyFunction}
-// //                     backgroundColor={returnEmptyString}
-// //                     parentActive={returnTrue}
-// //                     whenActiveChanged={emptyFunction}
-// //                     bringToFront={emptyFunction}
-// //                     ContainingCollectionView={undefined}
-// //                     ContainingCollectionDoc={undefined} />
-// //             </div>
-// //         );
-// //     }
-// // }
-
-// // 2
-// // Scripting.addGlobal(function onSwitchMobileInking() { return MobileInterface.Instance.onSwitchInking(); });
-// // Scripting.addGlobal(function renderMobileInking() { return MobileInterface.Instance.renderInkingContent(); });
-// // Scripting.addGlobal(function onSwitchMobileUpload() { return MobileInterface.Instance.onSwitchUpload(); });
-// // Scripting.addGlobal(function renderMobileUpload() { return MobileInterface.Instance.renderUploadContent(); });
-//     // Scripting.addGlobal(function addWebToMobileUpload() { return MobileInterface.Instance.addWebToCollection(); });
-
-
-// // 3
-//     // renderInkingContent = () => {
-//         //     console.log("rendering inking content");
-//         //     // TODO: support panning and zooming
-//         //     // TODO: handle moving of ink strokes
-//         //     if (this.mainContainer) {
-//         //         return (
-//         //             <div className="mobileInterface">
-//         //                 <div className="mobileInterface-inkInterfaceButtons">
-//         //                     <div className="navButtons">
-//         //                         <button className="mobileInterface-button cancel" onClick={this.onBack} title="Cancel drawing">BACK</button>
-//         //                     </div>
-//         //                     <div className="inkSettingButtons">
-//         //                         <button className="mobileInterface-button cancel" onClick={this.onBack} title="Cancel drawing"><FontAwesomeIcon icon="long-arrow-alt-left" /></button>
-//         //                     </div>
-//         //                     <div className="navButtons">
-//         //                         <button className="mobileInterface-button" onClick={this.shiftLeft} title="Shift left">left</button>
-//         //                         <button className="mobileInterface-button" onClick={this.shiftRight} title="Shift right">right</button>
-//         //                     </div>
-//         //                 </div>
-//         //                 <CollectionView
-//         //                     Document={this.mainContainer}
-//         //                     DataDoc={undefined}
-//         //                     LibraryPath={emptyPath}
-//         //                     fieldKey={""}
-//         //                     dropAction={"alias"}
-//         //                     bringToFront={emptyFunction}
-//         //                     addDocTab={returnFalse}
-//         //                     pinToPres={emptyFunction}
-//         //                     PanelWidth={this.panelWidth}
-//         //                     PanelHeight={this.panelHeight}
-//         //                     NativeHeight={returnZero}
-//         //                     NativeWidth={returnZero}
-//         //                     focus={emptyFunction}
-//         //                     isSelected={returnFalse}
-//         //                     select={emptyFunction}
-//         //                     active={returnFalse}
-//         //                     ContentScaling={returnOne}
-//         //                     whenActiveChanged={returnFalse}
-//         //                     ScreenToLocalTransform={Transform.Identity}
-//         //                     renderDepth={0}
-//         //                     ContainingCollectionView={undefined}
-//         //                     ContainingCollectionDoc={undefined}
-//         //                     rootSelected={returnTrue}>
-//         //                 </CollectionView>
-//         //             </div>
-//         //         );
-//         //     }
-//         // }
-
 @observer
 export class MobileInterface extends React.Component {
     @observable static Instance: MobileInterface;
@@ -1035,28 +138,6 @@ export class MobileInterface extends React.Component {
     @action
     toggleSidebar = () => this.sidebarActive = !this.sidebarActive
 
-    // toggleSidebar = () => {
-    //     if (this._open === false) {
-    //         this._open = true;
-    //     } else {
-    //         this._open = false;
-    //     }
-    //     console.log("clicked");
-    //     let menuButton = document.getElementById("menuButton") as HTMLElement;
-    //     //menuButton.classList.toggle('active');
-
-    //     let sidebar = document.getElementById("sidebar") as HTMLElement;
-    //     //sidebar.classList.toggle('active');
-
-    //     let header = document.getElementById("header") as HTMLElement;
-
-    //     if (!sidebar.classList.contains('active')) {
-    //         header.textContent = String(this._activeDoc.title);
-    //     } else {
-    //         header.textContent = "library";
-    //     }
-    // }
-
     /**
      * Method called when 'Library' button is pressed
      */
@@ -1134,66 +215,35 @@ export class MobileInterface extends React.Component {
     displayWorkspaces = () => {
         if (this.mainContainer) {
             const backgroundColor = () => "white";
-            if (this._activeDoc.title === "mobile audio") {
-                return (
-                    <div style={{ position: "relative", top: '600px', height: `calc(50% - 450px)`, width: "80%", overflow: "hidden", left: "10%", cursor: "pointer" }}>
-                        <DocumentView
-                            Document={this.mainContainer}
-                            DataDoc={undefined}
-                            LibraryPath={emptyPath}
-                            addDocument={returnFalse}
-                            addDocTab={returnFalse}
-                            pinToPres={emptyFunction}
-                            rootSelected={returnFalse}
-                            removeDocument={undefined}
-                            ScreenToLocalTransform={Transform.Identity}
-                            ContentScaling={returnOne}
-                            NativeHeight={returnZero}
-                            NativeWidth={returnZero}
-                            PanelWidth={() => window.screen.width}
-                            PanelHeight={() => window.screen.height}
-                            renderDepth={0}
-                            focus={emptyFunction}
-                            backgroundColor={backgroundColor}
-                            parentActive={returnTrue}
-                            whenActiveChanged={emptyFunction}
-                            bringToFront={emptyFunction}
-                            ContainingCollectionView={undefined}
-                            ContainingCollectionDoc={undefined}
-                        />
-                    </div>
-                );
-            } else {
-                return (
-                    <div style={{ position: "relative", top: '200px', height: `calc(100% - 200px)`, width: "100%", overflow: "hidden", left: "0%" }}>
-                        <DocumentView
-                            Document={this.mainContainer}
-                            DataDoc={undefined}
-                            LibraryPath={emptyPath}
-                            addDocument={returnFalse}
-                            addDocTab={returnFalse}
-                            pinToPres={emptyFunction}
-                            rootSelected={returnFalse}
-                            removeDocument={undefined}
-                            onClick={undefined}
-                            ScreenToLocalTransform={Transform.Identity}
-                            ContentScaling={returnOne}
-                            PanelWidth={this.returnWidth}
-                            PanelHeight={this.returnHeight}
-                            NativeHeight={returnZero}
-                            NativeWidth={returnZero}
-                            renderDepth={0}
-                            focus={emptyFunction}
-                            backgroundColor={backgroundColor}
-                            parentActive={returnTrue}
-                            whenActiveChanged={emptyFunction}
-                            bringToFront={emptyFunction}
-                            ContainingCollectionView={undefined}
-                            ContainingCollectionDoc={undefined}
-                        />
-                    </div>
-                );
-            }
+            return (
+                <div style={{ position: "relative", top: '200px', height: `calc(100% - 200px)`, width: "100%", overflow: "hidden", left: "0%" }}>
+                    <DocumentView
+                        Document={this.mainContainer}
+                        DataDoc={undefined}
+                        LibraryPath={emptyPath}
+                        addDocument={returnFalse}
+                        addDocTab={returnFalse}
+                        pinToPres={emptyFunction}
+                        rootSelected={returnFalse}
+                        removeDocument={undefined}
+                        onClick={undefined}
+                        ScreenToLocalTransform={Transform.Identity}
+                        ContentScaling={returnOne}
+                        PanelWidth={this.returnWidth}
+                        PanelHeight={this.returnHeight}
+                        NativeHeight={returnZero}
+                        NativeWidth={returnZero}
+                        renderDepth={0}
+                        focus={emptyFunction}
+                        backgroundColor={backgroundColor}
+                        parentActive={returnTrue}
+                        whenActiveChanged={emptyFunction}
+                        bringToFront={emptyFunction}
+                        ContainingCollectionView={undefined}
+                        ContainingCollectionDoc={undefined}
+                    />
+                </div>
+            );
         }
     }
 
@@ -1451,9 +501,9 @@ export class MobileInterface extends React.Component {
                 >
                     <div className={`toolbar ${this.activeToolbar ? "active" : ""}`}>
                         <div className="colorSelector">
-                            {/* <SketchPicker onChange={InkingControl.Instance.switchColor} presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent']} */}
+                            {/* <SketchPicker onChange={InkingControl.Instance.switchColor} presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent']}
                                 color={StrCast(CurrentUserUtils.ActivePen ? CurrentUserUtils.ActivePen.backgroundColor : undefined,
-                                StrCast(selDoc?._backgroundColor, StrCast(selDoc?.backgroundColor, "black")))} />
+                                StrCast(selDoc?._backgroundColor, StrCast(selDoc?.backgroundColor, "black")))} /> */}
                         </div>
                         <div className="widthSelector">
                             {/* <input type="range" min="1" max="100" defaultValue="2" id="myRange" onChange={(e: React.ChangeEvent<HTMLInputElement>) => InkingControl.Instance.switchWidth(e.target.value)} /> */}
diff --git a/src/mobile/MobileMenu.scss b/src/mobile/MobileMenu.scss
index 16eb035b3..f602b85a0 100644
--- a/src/mobile/MobileMenu.scss
+++ b/src/mobile/MobileMenu.scss
@@ -245,11 +245,12 @@ body {
     position: relative;
     width: 100px;
     height: 100px;
-    font-size: 90px;
+    font-size: 70px;
+    padding: 5px;
     text-align: center;
     border-style: solid;
     border-radius: 50px;
-    border-width: medium;
+    border-width: 5px;
     margin: 20px;
     z-index: 100;
 }
-- 
cgit v1.2.3-70-g09d2


From 57d4c562b6f0ef39dcd68f2985a56c4a683fcf49 Mon Sep 17 00:00:00 2001
From: geireann <60007097+geireann@users.noreply.github.com>
Date: Thu, 18 Jun 2020 04:38:08 +0800
Subject: pdf changes + radial menu + create new workspaces

(bug with ink)
---
 src/client/views/GestureOverlay.tsx                |  8 ---
 .../views/collections/CollectionStackingView.tsx   |  2 +-
 .../collectionFreeForm/InkOptionsMenu.tsx          |  4 +-
 src/client/views/nodes/DocumentView.tsx            | 12 ++--
 src/client/views/nodes/PDFBox.scss                 |  2 +-
 src/client/views/nodes/PDFBox.tsx                  |  7 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |  2 +-
 src/client/views/pdf/PDFViewer.tsx                 |  4 +-
 src/mobile/ImageUpload.tsx                         |  6 +-
 src/mobile/MobileInterface.tsx                     | 80 +++++++++++++++++++---
 src/server/ApiManagers/PDFManager.ts               |  3 +-
 11 files changed, 94 insertions(+), 36 deletions(-)

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

diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index e51e2d4e1..1c305ebeb 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -575,14 +575,6 @@ export default class GestureOverlay extends Touchable {
             const points = this._points.map(p => ({ X: p.X - B.left, Y: p.Y - B.top }));
             //push first points to so interactionUtil knows pointer is up
             this._points.push({ X: this._points[0].X, Y: this._points[0].Y });
-            if (MobileInterface.Instance && MobileInterface.Instance.drawingInk) {
-                DocServer.Mobile.dispatchGesturePoints({
-                    points: this._points,
-                    bounds: B,
-                    color: ActiveInkColor(),
-                    width: ActiveInkWidth()
-                });
-            }
 
             const initialPoint = this._points[0.];
             const xInGlass = initialPoint.X > (this._thumbX ?? Number.MAX_SAFE_INTEGER) && initialPoint.X < (this._thumbX ?? Number.MAX_SAFE_INTEGER) + (this.height);
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 797aabf18..9f1b5d63c 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -476,7 +476,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument)
                         transformOrigin: "top left",
                     }}
                     onScroll={action(e => {
-                        if (!this.props.isSelected() && this.props.renderDepth && window.innerWidth > 1000) e.currentTarget.scrollTop = this._scroll;
+                        if (!this.props.isSelected() && this.props.renderDepth && window.screen.width > 600) e.currentTarget.scrollTop = this._scroll;
                         else this._scroll = e.currentTarget.scrollTop;
                     })}
                     onDrop={this.onExternalDrop.bind(this)}
diff --git a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx
index 647847b68..676dc10f4 100644
--- a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx
+++ b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx
@@ -130,13 +130,13 @@ export default class InkOptionsMenu extends AntimodeMenu {
         ];
 
         const mobileButtons = [
-            this.shapeButtons,
+            ...this.shapeButtons,
             this.bezierButton,
             this.widthPicker,
             this.colorPicker,
         ];
 
-        return (window.innerWidth < 1000 ? this.getElement(mobileButtons) : this.getElement(buttons));
+        return (window.screen.width < 600 ? this.getElement(mobileButtons) : this.getElement(buttons));
     }
 }
 Scripting.addGlobal(function activatePen(penBtn: any) {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 75627607b..e027b6a0f 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -31,7 +31,7 @@ import { SelectionManager } from "../../util/SelectionManager";
 import SharingManager from '../../util/SharingManager';
 import { Transform } from "../../util/Transform";
 import { undoBatch, UndoManager } from "../../util/UndoManager";
-import { CollectionDockingView } from "../collections/CollectionDockingView";
+import { CollectionDockingView, DockedFrameRenderer } from "../collections/CollectionDockingView";
 import { CollectionView, CollectionViewType } from '../collections/CollectionView';
 import { ContextMenu } from "../ContextMenu";
 import { ContextMenuProps } from '../ContextMenuItem';
@@ -43,6 +43,7 @@ import "./DocumentView.scss";
 import { LinkAnchorBox } from './LinkAnchorBox';
 import { RadialMenu } from './RadialMenu';
 import React = require("react");
+import { MobileInterface } from '../../../mobile/MobileInterface';
 
 library.add(fa.faEdit, fa.faTrash, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faCompressArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faAlignCenter, fa.faCaretSquareRight,
     fa.faSquare, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faLink, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock, fa.faLock, fa.faLaptopCode, fa.faMale,
@@ -181,10 +182,11 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         const pt = me.touchEvent.touches[me.touchEvent.touches.length - 1];
         RadialMenu.Instance.openMenu(pt.pageX - 15, pt.pageY - 15);
 
-        RadialMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "map-pin", selected: -1 });
-        RadialMenu.Instance.addItem({ description: "Delete this document", event: () => { this.props.ContainingCollectionView?.removeDocument(this.props.Document), RadialMenu.Instance.closeMenu(); }, icon: "layer-group", selected: -1 });
-        RadialMenu.Instance.addItem({ description: "Open in a new tab", event: () => this.props.addDocTab(this.props.Document, "onRight"), icon: "trash", selected: -1 });
-        RadialMenu.Instance.addItem({ description: "Pin to Presentation", event: () => this.props.pinToPres(this.props.Document), icon: "folder", selected: -1 });
+        // RadialMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "map-pin", selected: -1 });
+        RadialMenu.Instance.addItem({ description: "Delete", event: () => { this.props.ContainingCollectionView?.removeDocument(this.props.Document), RadialMenu.Instance.closeMenu(); }, icon: "external-link-square-alt", selected: -1 });
+        // RadialMenu.Instance.addItem({ description: "Open in a new tab", event: () => this.props.addDocTab(this.props.Document, "onRight"), icon: "trash", selected: -1 });
+        RadialMenu.Instance.addItem({ description: "Pin", event: () => DockedFrameRenderer.PinDoc(this.props.Document), icon: "map-pin", selected: -1 });
+        RadialMenu.Instance.addItem({ description: "Open", event: () => MobileInterface.Instance.handleClick(this.props.Document), icon: "trash", selected: -1 });
 
         SelectionManager.DeselectAll();
     }
diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss
index 474587159..1a31d2916 100644
--- a/src/client/views/nodes/PDFBox.scss
+++ b/src/client/views/nodes/PDFBox.scss
@@ -224,7 +224,7 @@
     }
 }
 
-@media only screen and (max-width: 1000px) {
+@media only screen and (max-width: 600px) {
 
     .pdfBox .pdfBox-ui .pdfBox-settingsCont .pdfBox-settingsButton,
     .pdfBox-interactive .pdfBox-ui .pdfBox-settingsCont .pdfBox-settingsButton {
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 78b7faeee..4b4348d3c 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -215,13 +215,14 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
 
     @computed get contentScaling() { return this.props.ContentScaling(); }
     @computed get renderTitleBox() {
-        console.log("fitWidth ?: " + !(this.props.Document._fitWidth) && (window.innerWidth > 1000));
+        console.log("fitWidth ?: " + !(this.props.Document._fitWidth) && (window.screen.width > 600));
         console.log("_nativeHeight: " + this.Document._nativeHeight);
         console.log("%: " + `${100 / this.contentScaling}%`);
         const classname = "pdfBox" + (this.active() ? "-interactive" : "");
         return <div className={classname} style={{
             width: !this.props.Document._fitWidth ? this.Document._nativeWidth || 0 : `${100 / this.contentScaling}%`,
-            height: !this.props.Document._fitWidth && (window.innerWidth > 1000) ? this.Document._nativeHeight || 0 : `${100 / this.contentScaling}%`, //Adjusted for mobile (!window.innerWidth < 1000)
+            //height adjusted for mobile (window.screen.width > 600)
+            height: !this.props.Document._fitWidth && (window.screen.width > 600) ? this.Document._nativeHeight || 0 : `${100 / this.contentScaling}%`,
             transform: `scale(${this.contentScaling})`
         }}  >
             <div className="pdfBox-title-outer">
@@ -233,7 +234,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
     isChildActive = (outsideReaction?: boolean) => this._isChildActive;
     @computed get renderPdfView() {
         const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField);
-        return <div className={"pdfBox"} onContextMenu={this.specificContextMenu} style={{ height: this.props.Document._scrollTop && !this.Document._fitWidth && (window.innerWidth > 1000) ? NumCast(this.Document._height) * this.props.PanelWidth() / NumCast(this.Document._width) : undefined }}>
+        return <div className={"pdfBox"} onContextMenu={this.specificContextMenu} style={{ height: this.props.Document._scrollTop && !this.Document._fitWidth && (window.screen.width > 600) ? NumCast(this.Document._height) * this.props.PanelWidth() / NumCast(this.Document._width) : undefined }}>
             <PDFViewer {...this.props} pdf={this._pdf!} url={pdfUrl!.url.pathname} active={this.props.active} loaded={this.loaded}
                 setPdfViewer={this.setPdfViewer} ContainingCollectionView={this.props.ContainingCollectionView}
                 renderDepth={this.props.renderDepth} PanelHeight={this.props.PanelHeight} PanelWidth={this.props.PanelWidth}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index f3d0d135c..ae508cd67 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -261,7 +261,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     }
 
     public unhighlightSearchTerms = () => {
-        if (window.innerWidth < 1000) null;
+        if (window.screen.width < 600) null;
         else if (this._editorView && (this._editorView as any).docView) {
             const mark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight);
             const activeMark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight, { selected: true });
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 9cdbea2da..57b7bceca 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -709,8 +709,8 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
             onScroll={this.onScroll} onWheel={this.onZoomWheel} onPointerDown={this.onPointerDown} onClick={this.onClick}
             style={{
                 overflowX: this._zoomed !== 1 ? "scroll" : undefined,
-                width: !this.props.Document._fitWidth && (window.innerWidth > 1000) ? NumCast(this.props.Document._nativeWidth) : `${100 / this.contentScaling}%`,
-                height: !this.props.Document._fitWidth && (window.innerWidth > 1000) ? NumCast(this.props.Document._nativeHeight) : `${100 / this.contentScaling}%`,
+                width: !this.props.Document._fitWidth && (window.screen.width > 600) ? NumCast(this.props.Document._nativeWidth) : `${100 / this.contentScaling}%`,
+                height: !this.props.Document._fitWidth && (window.screen.width > 600) ? NumCast(this.props.Document._nativeHeight) : `${100 / this.contentScaling}%`,
                 transform: `scale(${this.props.ContentScaling()})`
             }}  >
             {this.pdfViewerDiv}
diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx
index d8b1913ee..b66f0461d 100644
--- a/src/mobile/ImageUpload.tsx
+++ b/src/mobile/ImageUpload.tsx
@@ -65,8 +65,11 @@ export class Uploader extends React.Component {
                             }
                             const path = Utils.prepend(result.accessPaths.agnostic.client);
                             let doc = null;
+                            console.log("type: " + file.type);
                             if (file.type === "video/mp4") {
                                 doc = Docs.Create.VideoDocument(path, { _nativeWidth: 200, _width: 200, title: name });
+                            } else if (file.type === "application/pdf") {
+                                doc = Docs.Create.PdfDocument(path, { _width: 200, title: name });
                             } else {
                                 doc = Docs.Create.ImageDocument(path, { _nativeWidth: 200, _width: 200, title: name });
                             }
@@ -175,7 +178,7 @@ export class Uploader extends React.Component {
     private get uploadInterface() {
         return (
             <div className="imgupload_cont">
-                <input type="file" accept="video/*,image/*" className="inputFile" id="input_image_file" ref={inputRef} onChange={this.inputLabel} multiple></input>
+                <input type="file" accept="application/pdf, video/*,image/*" className="inputFile" id="input_image_file" ref={inputRef} onChange={this.inputLabel} multiple></input>
                 <label className="file" id="label" htmlFor="input_image_file">{this.nm}</label>
                 <div className="upload_label" onClick={this.onClick}>
                     <FontAwesomeIcon icon="upload" size="sm" />
@@ -217,4 +220,3 @@ export class Uploader extends React.Component {
 }
 
 
-// DocServer.init(window.location.protocol, window.location.hostname, 4321, "image upload");
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index 5acdc1dea..644535179 100644
--- a/src/mobile/MobileInterface.tsx
+++ b/src/mobile/MobileInterface.tsx
@@ -1,7 +1,7 @@
 import * as React from "react";
 import { library } from '@fortawesome/fontawesome-svg-core';
 import {
-    faTasks, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus,
+    faTasks, faExternalLinkSquareAlt, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus,
     faTerminal, faToggleOn, faFile as fileSolid, faExternalLinkAlt, faLocationArrow, faSearch, faFileDownload, faStop, faCalculator, faWindowMaximize, faAddressCard,
     faQuestionCircle, faArrowLeft, faArrowRight, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt,
     faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter,
@@ -17,7 +17,7 @@ import { FieldValue, Cast } from '../fields/Types';
 import { CurrentUserUtils } from '../client/util/CurrentUserUtils';
 import { emptyPath, emptyFunction, returnFalse, returnOne, returnTrue, returnZero, Utils } from '../Utils';
 import { DocServer } from '../client/DocServer';
-import { Docs } from '../client/documents/Documents';
+import { Docs, DocumentOptions } from '../client/documents/Documents';
 import { Scripting } from '../client/util/Scripting';
 import { DocumentView } from '../client/views/nodes/DocumentView';
 import { Transform } from '../client/util/Transform';
@@ -36,8 +36,11 @@ import GestureOverlay from "../client/views/GestureOverlay";
 import { ScriptField } from "../fields/ScriptField";
 import InkOptionsMenu from "../client/views/collections/collectionFreeForm/InkOptionsMenu";
 import { RadialMenu } from "../client/views/nodes/RadialMenu";
+import { UndoManager } from "../client/util/UndoManager";
+import { MainView } from "../client/views/MainView";
+import { List } from "../fields/List";
 
-library.add(faTasks, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus,
+library.add(faTasks, faExternalLinkSquareAlt, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus,
     faTerminal, faToggleOn, fileSolid, faExternalLinkAlt, faLocationArrow, faSearch, faFileDownload, faStop, faCalculator, faWindowMaximize, faAddressCard,
     faQuestionCircle, faArrowLeft, faArrowRight, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt,
     faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter,
@@ -149,7 +152,7 @@ export class MobileInterface extends React.Component {
      * Return 'Home", which implies returning to 'Home' buttons
      */
     returnHome = () => {
-        if (this._homeMenu === false || this.sidebarActive === true) {
+        if (this._homeMenu || this.sidebarActive) {
             this._homeMenu = true;
             this._parents = [];
             this._activeDoc = this._homeDoc;
@@ -220,7 +223,7 @@ export class MobileInterface extends React.Component {
      */
     handleClick = async (doc: Doc) => {
         const children = DocListCast(doc.data);
-        if (doc.type !== "collection") {
+        if (doc.type !== "collection" && this.sidebarActive) {
             this._parents.push(this._activeDoc);
             this._activeDoc = doc;
             this.switchCurrentView((userDoc: Doc) => doc);
@@ -333,7 +336,7 @@ export class MobileInterface extends React.Component {
 
     // Renders the contents of the menu and sidebar
     renderDefaultContent = () => {
-        if (this._homeMenu === true) {
+        if (this._homeMenu) {
             return (
                 <div>
                     <div className="navbar">
@@ -351,7 +354,7 @@ export class MobileInterface extends React.Component {
                         <div className="sidebarButtons">
                             <div
                                 className="item"
-                                onClick={() => ScriptField.MakeScript("createNewWorkspace()")}>Create New Workspace
+                                onClick={() => MainView.Instance?.createNewWorkspace()}>Create New Workspace
                             </div>
                         </div>
                     </div>
@@ -403,7 +406,10 @@ export class MobileInterface extends React.Component {
                                 {buttons}
                                 <div
                                     className="item"
-                                    onClick={() => ScriptField.MakeScript("createNewWorkspace()")}>Create New Workspace
+                                    style={{ opacity: 0.7 }}
+                                    onClick={() => this.createNewWorkspace()}>
+                                    <FontAwesomeIcon className="right" icon="plus" size="lg" />
+                                    <div className="item-type">Create New Workspace</div>
                                 </div>
                             </>
                         }
@@ -413,6 +419,32 @@ export class MobileInterface extends React.Component {
         );
     }
 
+    /**
+     * Handles the Create New Workspace button in the menu
+     */
+    @action
+    createNewWorkspace = async (id?: string) => {
+        const workspaces = Cast(this.userDoc.myWorkspaces, Doc) as Doc;
+        const workspaceCount = DocListCast(workspaces.data).length + 1;
+        const freeformOptions: DocumentOptions = {
+            x: 0,
+            y: 400,
+            title: "Collection " + workspaceCount,
+            _LODdisable: true
+        };
+        const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions);
+        const workspaceDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [Doc.UserDoc().myCatalog as Doc] }], { title: `Workspace ${workspaceCount}` }, id, "row");
+
+        const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`);
+        const toggleComic = ScriptField.MakeScript(`toggleComicMode()`);
+        const cloneWorkspace = ScriptField.MakeScript(`cloneWorkspace()`);
+        workspaceDoc.contextMenuScripts = new List<ScriptField>([toggleTheme!, toggleComic!, cloneWorkspace!]);
+        workspaceDoc.contextMenuLabels = new List<string>(["Toggle Theme Colors", "Toggle Comic Mode", "New Workspace Layout"]);
+
+        Doc.AddDocToList(workspaces, "data", workspaceDoc);
+        // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
+    }
+
     stop = (e: React.MouseEvent) => {
         e.stopPropagation();
     }
@@ -431,7 +463,7 @@ export class MobileInterface extends React.Component {
         }
     }
 
-    // Button for switching between pan and ink mode
+    // Button for switching between pen and ink mode
     @action
     onSwitchInking = () => {
         const button = document.getElementById("inkButton") as HTMLElement;
@@ -465,6 +497,16 @@ export class MobileInterface extends React.Component {
         if (this._activeDoc._viewType === "docking") {
             return (
                 <>
+                    {/* <div className="docButton"
+                        id="undoButton"
+                        title="undo"
+                        onClick={(e: React.MouseEvent) => {
+                            UndoManager.Undo();
+                            e.stopPropagation();
+                        }}>
+                        <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="undo-alt"
+                        />
+                    </div> */}
                     <div className="docButton"
                         id="inkButton"
                         title={Doc.isDocPinned(this._activeDoc) ? "Pen on" : "Pen off"}
@@ -472,6 +514,16 @@ export class MobileInterface extends React.Component {
                         <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="pen-nib"
                         />
                     </div>
+                    {/* <div className="docButton"
+                        id="redoButton"
+                        title="redo"
+                        onClick={(e: React.MouseEvent) => {
+                            UndoManager.Redo();
+                            e.stopPropagation();
+                        }}>
+                        <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="redo-alt"
+                        />
+                    </div> */}
                 </>);
         }
     }
@@ -645,6 +697,12 @@ export class MobileInterface extends React.Component {
         );
     }
 
+    displayRadialMenu = () => {
+        if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc) {
+            return <RadialMenu />;
+        }
+    }
+
     onDragOver = (e: React.DragEvent) => {
         e.preventDefault();
         e.stopPropagation();
@@ -669,12 +727,14 @@ export class MobileInterface extends React.Component {
                     {this.displayWorkspaces()}
                     {this.renderDefaultContent()}
                 </GestureOverlay>
-                <RadialMenu />
+                {this.displayRadialMenu()}
             </div>
         );
     }
 }
 
+
+
 Scripting.addGlobal(function switchMobileView(doc: (userDoc: Doc) => Doc, renderView?: () => JSX.Element, onSwitch?: () => void) { return MobileInterface.Instance.switchCurrentView(doc, renderView, onSwitch); });
 Scripting.addGlobal(function openMobilePresentation() { return MobileInterface.Instance.setupDefaultPresentation(); });
 Scripting.addGlobal(function toggleMobileSidebar() { return MobileInterface.Instance.toggleSidebar(); });
diff --git a/src/server/ApiManagers/PDFManager.ts b/src/server/ApiManagers/PDFManager.ts
index d2a9e9cce..b0b5a484a 100644
--- a/src/server/ApiManagers/PDFManager.ts
+++ b/src/server/ApiManagers/PDFManager.ts
@@ -55,7 +55,8 @@ async function CreateThumbnail(coreFilename: string, pageNum: number, res: expre
     const documentProxy = await Pdfjs.getDocument(sourcePath).promise;
     const factory = new NodeCanvasFactory();
     const page = await documentProxy.getPage(pageNum);
-    const viewport = page.getViewport(1 as any);
+    const scale = 1;
+    const viewport = page.getViewport(scale as any);
     const { canvas, context } = factory.create(viewport.width, viewport.height);
     const renderContext = {
         canvasContext: context,
-- 
cgit v1.2.3-70-g09d2


From 6df649ae1228f191a5654e45e898880b130afd28 Mon Sep 17 00:00:00 2001
From: Lionel Han <47760119+IGoByJoe@users.noreply.github.com>
Date: Fri, 19 Jun 2020 21:43:56 -0700
Subject: fixed icon appearing over sidebar bug

---
 src/client/views/GestureOverlay.tsx |  4 ++--
 src/mobile/MobileInterface.tsx      | 14 +++++++-------
 2 files changed, 9 insertions(+), 9 deletions(-)

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

diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 1c305ebeb..2121b27f0 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -157,8 +157,8 @@ export default class GestureOverlay extends Touchable {
                 // -- radial menu code --
                 this._holdTimer = setTimeout(() => {
                     console.log("hold");
-                    const target = document.elementFromPoint(te.changedTouches.item(0).clientX, te.changedTouches.item(0).clientY);
-                    const pt: any = te.touches[te.touches.length - 1];
+                    const target = document.elementFromPoint(te.changedTouches?.item(0).clientX, te.changedTouches?.item(0).clientY);
+                    const pt: any = te.touches[te.touches?.length - 1];
                     if (nts.nt.length === 1 && pt.radiusX > 1 && pt.radiusY > 1) {
                         target?.dispatchEvent(
                             new CustomEvent<InteractionUtils.MultiTouchEvent<React.TouchEvent>>("dashOnTouchHoldStart",
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index 2fde359aa..63c7873f4 100644
--- a/src/mobile/MobileInterface.tsx
+++ b/src/mobile/MobileInterface.tsx
@@ -760,15 +760,15 @@ export class MobileInterface extends React.Component {
                 </div>
                 {this.switchMenuView()}
                 {this.inkMenu()}
-                <div className="docButtonContainer">
-                    {this.uploadImageButton()}
-                    {this.pinToPresentation()}
-                    {this.downloadDocument()}
-                    {this.drawInk()}
-                    {this.uploadAudioButton()}
 
-                </div>
                 <GestureOverlay>
+                    <div className="docButtonContainer">
+                        {this.uploadImageButton()}
+                        {this.pinToPresentation()}
+                        {this.downloadDocument()}
+                        {this.drawInk()}
+                        {this.uploadAudioButton()}
+                    </div>
                     {this.displayWorkspaces()}
                     {this.renderDefaultContent()}
                 </GestureOverlay>
-- 
cgit v1.2.3-70-g09d2


From ecd3c3b0a713a594d4d0f4295bad017af1ba47ba Mon Sep 17 00:00:00 2001
From: Lionel Han <47760119+IGoByJoe@users.noreply.github.com>
Date: Sat, 27 Jun 2020 21:46:17 -0700
Subject: some changes

---
 src/client/views/GestureOverlay.tsx | 2 +-
 src/mobile/MobileInterface.tsx      | 4 ++++
 src/mobile/MobileMenu.scss          | 2 +-
 3 files changed, 6 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 98777a92c..e82609e7e 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -260,7 +260,7 @@ export default class GestureOverlay extends Touchable {
     handleHandDown = async (e: React.TouchEvent) => {
         this._holdTimer && clearTimeout(this._holdTimer);
 
-        // this chunk of code helps us keep track of which touch events are associated with a hand event
+        // this chunk of code helps us keep track of which touch events ar e associated with a hand event
         // so that if a hand is held down, but a second hand is interacting with dash, the second hand's events
         // won't interfere with the first hand's events.
         const fingers = new Array<React.Touch>();
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index 0bc950a71..d0848aea2 100644
--- a/src/mobile/MobileInterface.tsx
+++ b/src/mobile/MobileInterface.tsx
@@ -12,6 +12,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import { trace } from 'mobx';
+import { TraceMobx } from "../fields/util";
 import * as rp from 'request-promise';
 import { Doc, DocListCast } from '../fields/Doc';
 import { CurrentUserUtils } from '../client/util/CurrentUserUtils';
@@ -788,6 +789,7 @@ export class MobileInterface extends React.Component {
     }
 
     onDragOver = (e: React.DragEvent) => {
+        console.log("drag!");
         e.preventDefault();
         e.stopPropagation();
     }
@@ -816,6 +818,8 @@ export class MobileInterface extends React.Component {
     }
 
     render() {
+        // trace();
+        // TraceMobx();
         return (
             <div className="mobileInterface-container" onDragOver={this.onDragOver}>
                 <SettingsManager />
diff --git a/src/mobile/MobileMenu.scss b/src/mobile/MobileMenu.scss
index ec8946578..24d72dec6 100644
--- a/src/mobile/MobileMenu.scss
+++ b/src/mobile/MobileMenu.scss
@@ -248,7 +248,7 @@ body {
 .sidebar.active {
     position: absolute;
     right:0%;
-    opacity: 1;
+    opacity: 0.8;
     z-index: 101;
 }
 
-- 
cgit v1.2.3-70-g09d2


From 1daf0a496175267d86f495bb24aa5140b6a9eeab Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 2 Jul 2020 14:05:33 -0400
Subject: small clanup in Mobile related code

---
 src/client/views/GestureOverlay.tsx                |  2 +-
 src/client/views/collections/CollectionView.tsx    | 21 ++++++++--------
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 11 ++++----
 src/client/views/nodes/DocumentView.tsx            | 29 +++++++++++-----------
 .../views/nodes/formattedText/FormattedTextBox.tsx |  2 +-
 5 files changed, 33 insertions(+), 32 deletions(-)

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

diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 839ab09c7..487467b2b 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -264,7 +264,7 @@ export default class GestureOverlay extends Touchable {
     handleHandDown = async (e: React.TouchEvent) => {
         this._holdTimer && clearTimeout(this._holdTimer);
 
-        // this chunk of code helps us keep track of which touch events ar e associated with a hand event
+        // this chunk of code helps us keep track of which touch events are associated with a hand event
         // so that if a hand is held down, but a second hand is interacting with dash, the second hand's events
         // won't interfere with the first hand's events.
         const fingers = new Array<React.Touch>();
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 35196b634..300309882 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -231,12 +231,12 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
 
 
     setupViewTypes(category: string, func: (viewType: CollectionViewType) => Doc, addExtras: boolean) {
-        const existingVm = ContextMenu.Instance?.findByDescription(category);
+        const existingVm = ContextMenu.Instance.findByDescription(category);
         const subItems = existingVm && "subitems" in existingVm ? existingVm.subitems : [];
 
         subItems.push({ description: "Freeform", event: () => func(CollectionViewType.Freeform), icon: "signature" });
         if (addExtras && CollectionView._safeMode) {
-            ContextMenu.Instance?.addItem({ description: "Test Freeform", event: () => func(CollectionViewType.Invalid), icon: "project-diagram" });
+            ContextMenu.Instance.addItem({ description: "Test Freeform", event: () => func(CollectionViewType.Invalid), icon: "project-diagram" });
         }
         subItems.push({ description: "Schema", event: () => func(CollectionViewType.Schema), icon: "th-list" });
         subItems.push({ description: "Tree", event: () => func(CollectionViewType.Tree), icon: "tree" });
@@ -255,11 +255,12 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
             subItems.push({ description: "Custom", icon: "fingerprint", event: AddCustomFreeFormLayout(this.props.Document, this.props.fieldKey) });
         }
         addExtras && subItems.push({ description: "lightbox", event: action(() => this._isLightboxOpen = true), icon: "eye" });
-        !existingVm && ContextMenu.Instance?.addItem({ description: category, subitems: subItems, icon: "eye" });
+        !existingVm && ContextMenu.Instance.addItem({ description: category, subitems: subItems, icon: "eye" });
     }
 
     onContextMenu = (e: React.MouseEvent): void => {
-        if (!e.isPropagationStopped() && this.props.Document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
+        const cm = ContextMenu.Instance;
+        if (cm && !e.isPropagationStopped() && this.props.Document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
             this.setupViewTypes("Add a Perspective...", vtype => {
                 const newRendition = Doc.MakeAlias(this.props.Document);
                 newRendition._viewType = vtype;
@@ -267,7 +268,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                 return newRendition;
             }, false);
 
-            const existing = ContextMenu.Instance?.findByDescription("Options...");
+            const existing = cm.findByDescription("Options...");
             const layoutItems = existing && "subitems" in existing ? existing.subitems : [];
             layoutItems.push({ description: `${this.props.Document.forceActive ? "Select" : "Force"} Contents Active`, event: () => this.props.Document.forceActive = !this.props.Document.forceActive, icon: "project-diagram" });
             if (this.props.Document.childLayout instanceof Doc) {
@@ -278,9 +279,9 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
             }
             layoutItems.push({ description: `${this.props.Document.isInPlaceContainer ? "Unset" : "Set"} inPlace Container`, event: () => this.props.Document.isInPlaceContainer = !this.props.Document.isInPlaceContainer, icon: "project-diagram" });
 
-            !existing && ContextMenu.Instance?.addItem({ description: "Options...", subitems: layoutItems, icon: "hand-point-right" });
+            !existing && cm.addItem({ description: "Options...", subitems: layoutItems, icon: "hand-point-right" });
 
-            const existingOnClick = ContextMenu.Instance?.findByDescription("OnClick...");
+            const existingOnClick = cm.findByDescription("OnClick...");
             const onClicks = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
             const funcs = [
                 { key: "onChildClick", name: "On Child Clicked" },
@@ -296,13 +297,13 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                     icon: "edit",
                     event: () => this.props.Document[StrCast(childClick.targetScriptKey)] = ObjectField.MakeCopy(ScriptCast(childClick.data)),
                 }));
-            !existingOnClick && ContextMenu.Instance?.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" });
+            !existingOnClick && cm.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" });
 
             if (!Doc.UserDoc().noviceMode) {
-                const more = ContextMenu.Instance?.findByDescription("More...");
+                const more = cm.findByDescription("More...");
                 const moreItems = more && "subitems" in more ? more.subitems : [];
                 moreItems.push({ description: "Export Image Hierarchy", icon: "columns", event: () => ImageUtils.ExportHierarchyToFileSystem(this.props.Document) });
-                !more && ContextMenu.Instance?.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" });
+                !more && cm.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" });
             }
         }
     }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index ae7213d0b..21b0473c9 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -602,7 +602,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     pan = (e: PointerEvent | React.Touch | { clientX: number, clientY: number }): void => {
         // bcz: theres should be a better way of doing these than referencing these static instances directly
         MarqueeOptionsMenu.Instance?.fadeOut(true);// I think it makes sense for the marquee menu to go away when panned. -syip2
-        // PDFMenu.Instance.fadeOut(true);
 
         const [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
         this.setPan((this.Document._panX || 0) - dx, (this.Document._panY || 0) - dy, undefined, true);
@@ -1204,17 +1203,17 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     private thumbIdentifier?: number;
 
     onContextMenu = (e: React.MouseEvent) => {
-        if (this.props.annotationsKey) return;
+        if (this.props.annotationsKey || !ContextMenu.Instance) return;
 
-        const appearance = ContextMenu.Instance?.findByDescription("Appearance...");
+        const appearance = ContextMenu.Instance.findByDescription("Appearance...");
         const appearanceItems = appearance && "subitems" in appearance ? appearance.subitems : [];
         appearanceItems.push({ description: "reset view", event: () => { this.props.Document._panX = this.props.Document._panY = 0; this.props.Document[this.scaleFieldKey] = 1; }, icon: "compress-arrows-alt" });
         appearanceItems.push({ description: `${this.fitToContent ? "Unset" : "Set"} Fit To Container`, event: () => this.Document._fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" });
         appearanceItems.push({ description: `${this.Document.useClusters ? "Uncluster" : "Use Clusters"}`, event: () => this.updateClusters(!this.Document.useClusters), icon: "braille" });
         appearanceItems.push({ description: "Use Background Color as Default", event: () => Cast(Doc.UserDoc().emptyCollection, Doc, null)._backgroundColor = StrCast(this.layoutDoc._backgroundColor), icon: "palette" });
-        !appearance && ContextMenu.Instance?.addItem({ description: "Appearance...", subitems: appearanceItems, icon: "eye" });
+        !appearance && ContextMenu.Instance.addItem({ description: "Appearance...", subitems: appearanceItems, icon: "eye" });
 
-        const options = ContextMenu.Instance?.findByDescription("Options...");
+        const options = ContextMenu.Instance.findByDescription("Options...");
         const optionItems = options && "subitems" in options ? options.subitems : [];
         !this.props.isAnnotationOverlay &&
             optionItems.push({ description: (this.showTimeline ? "Close" : "Open") + " Animation Timeline", event: action(() => this.showTimeline = !this.showTimeline), icon: faEye });
@@ -1254,7 +1253,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                 }
             });
         }
-        !options && ContextMenu.Instance?.addItem({ description: "Options...", subitems: optionItems, icon: "eye" });
+        !options && ContextMenu.Instance.addItem({ description: "Options...", subitems: optionItems, icon: "eye" });
 
     }
     @observable showTimeline = false;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 8d122baeb..732089068 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -736,21 +736,22 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         }
 
         const cm = ContextMenu.Instance;
+        if (!cm) return;
 
         const customScripts = Cast(this.props.Document.contextMenuScripts, listSpec(ScriptField), []);
         Cast(this.props.Document.contextMenuLabels, listSpec("string"), []).forEach((label, i) =>
-            cm?.addItem({ description: label, event: () => customScripts[i]?.script.run({ this: this.layoutDoc, self: this.rootDoc }), icon: "sticky-note" }));
+            cm.addItem({ description: label, event: () => customScripts[i]?.script.run({ this: this.layoutDoc, self: this.rootDoc }), icon: "sticky-note" }));
         this.props.contextMenuItems?.().forEach(item =>
-            cm?.addItem({ description: item.label, event: () => item.script.script.run({ this: this.layoutDoc, self: this.rootDoc }), icon: "sticky-note" }));
+            cm.addItem({ description: item.label, event: () => item.script.script.run({ this: this.layoutDoc, self: this.rootDoc }), icon: "sticky-note" }));
 
         const options = cm.findByDescription("Options...");
         const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : [];
         const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null);
         templateDoc && optionItems.push({ description: "Open Template   ", event: () => this.props.addDocTab(templateDoc, "onRight"), icon: "eye" });
         optionItems.push({ description: "Toggle Show Each Link Dot", event: () => this.layoutDoc.showLinks = !this.layoutDoc.showLinks, icon: "eye" });
-        !options && cm?.addItem({ description: "Options...", subitems: optionItems, icon: "compass" });
+        !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "compass" });
 
-        const existingOnClick = cm?.findByDescription("OnClick...");
+        const existingOnClick = cm.findByDescription("OnClick...");
         const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
         onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" });
         onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`), icon: "window-restore" });
@@ -759,17 +760,17 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link on Right", event: this.toggleFollowOnRight, icon: "concierge-bell" });
         onClicks.push({ description: this.Document.isLinkButton || this.onClickHandler ? "Remove Click Behavior" : "Follow Link", event: this.toggleLinkButtonBehavior, icon: "concierge-bell" });
         onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "edit" });
-        !existingOnClick && cm?.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" });
+        !existingOnClick && cm.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" });
 
         const funcs: ContextMenuProps[] = [];
         if (this.layoutDoc.onDragStart) {
             funcs.push({ description: "Drag an Alias", icon: "edit", event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getAlias(this.dragFactory)')) });
             funcs.push({ description: "Drag a Copy", icon: "edit", event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')) });
             funcs.push({ description: "Drag Document", icon: "edit", event: () => this.layoutDoc.onDragStart = undefined });
-            cm?.addItem({ description: "OnDrag...", subitems: funcs, icon: "asterisk" });
+            cm.addItem({ description: "OnDrag...", subitems: funcs, icon: "asterisk" });
         }
 
-        const more = cm?.findByDescription("More...");
+        const more = cm.findByDescription("More...");
         const moreItems = more && "subitems" in more ? more.subitems : [];
         if (!Doc.UserDoc().noviceMode) {
             moreItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc), icon: "concierge-bell" });
@@ -798,16 +799,16 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" });
         moreItems.push({ description: "Delete", event: this.deleteClicked, icon: "trash" });
         moreItems.push({ description: "Share", event: () => SharingManager.Instance.open(this), icon: "external-link-alt" });
-        !more && cm?.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" });
-        cm?.moveAfter(cm?.findByDescription("More...")!, cm?.findByDescription("OnClick...")!);
+        !more && cm.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" });
+        cm.moveAfter(cm.findByDescription("More...")!, cm.findByDescription("OnClick...")!);
 
-        const help = cm?.findByDescription("Help...");
+        const help = cm.findByDescription("Help...");
         const helpItems: ContextMenuProps[] = help && "subitems" in help ? help.subitems : [];
         helpItems.push({ description: "Text Shortcuts Ctrl+/", event: () => this.props.addDocTab(Docs.Create.PdfDocument("http://localhost:1050/assets/cheat-sheet.pdf", { _width: 300, _height: 300 }), "onRight"), icon: "keyboard" });
         helpItems.push({ description: "Show Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "layer-group" });
-        cm?.addItem({ description: "Help...", subitems: helpItems, icon: "question" });
+        cm.addItem({ description: "Help...", subitems: helpItems, icon: "question" });
 
-        const existingAcls = cm?.findByDescription("Privacy...");
+        const existingAcls = cm.findByDescription("Privacy...");
         const aclItems: ContextMenuProps[] = existingAcls && "subitems" in existingAcls ? existingAcls.subitems : [];
         aclItems.push({ description: "Make Add Only", event: () => this.setAcl("addOnly"), icon: "concierge-bell" });
         aclItems.push({ description: "Make Read Only", event: () => this.setAcl("readOnly"), icon: "concierge-bell" });
@@ -815,7 +816,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         aclItems.push({ description: "Make Editable", event: () => this.setAcl("write"), icon: "concierge-bell" });
         aclItems.push({ description: "Test Private", event: () => this.testAcl("ownerOnly"), icon: "concierge-bell" });
         aclItems.push({ description: "Test Readonly", event: () => this.testAcl("readOnly"), icon: "concierge-bell" });
-        !existingAcls && cm?.addItem({ description: "Privacy...", subitems: aclItems, icon: "question" });
+        !existingAcls && cm.addItem({ description: "Privacy...", subitems: aclItems, icon: "question" });
 
         // const recommender_subitems: ContextMenuProps[] = [];
 
@@ -876,7 +877,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 // DocumentViews should stop propagation of this event
                 e.stopPropagation();
             }
-            ContextMenu.Instance?.displayMenu(e.pageX - 15, e.pageY - 15);
+            cm.displayMenu(e.pageX - 15, e.pageY - 15);
             !SelectionManager.IsSelected(this, true) && SelectionManager.SelectDoc(this, false);
         });
         const path = this.props.LibraryPath.reduce((p: string, d: Doc) => p + "/" + (Doc.AreProtosEqual(d, (Doc.UserDoc()["tabs-button-library"] as Doc).sourcePanel as Doc) ? "" : d.title), "");
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 270fcb01c..b127cd024 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -190,7 +190,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                 }
             }
             const state = this._editorView.state.apply(tx);
-            this._editorView?.updateState(state);
+            this._editorView.updateState(state);
             (tx.storedMarks && !this._editorView.state.storedMarks) && (this._editorView.state.storedMarks = tx.storedMarks);
 
             const tsel = this._editorView.state.selection.$from;
-- 
cgit v1.2.3-70-g09d2

