aboutsummaryrefslogtreecommitdiff
path: root/src/mobile
diff options
context:
space:
mode:
Diffstat (limited to 'src/mobile')
-rw-r--r--src/mobile/AudioUpload.tsx94
-rw-r--r--src/mobile/ImageUpload.tsx61
-rw-r--r--src/mobile/MobileHome.scss101
-rw-r--r--src/mobile/MobileInterface.scss448
-rw-r--r--src/mobile/MobileInterface.tsx286
-rw-r--r--src/mobile/MobileMenu.scss475
6 files changed, 594 insertions, 871 deletions
diff --git a/src/mobile/AudioUpload.tsx b/src/mobile/AudioUpload.tsx
index f859b0ba3..590bf8f9d 100644
--- a/src/mobile/AudioUpload.tsx
+++ b/src/mobile/AudioUpload.tsx
@@ -1,62 +1,78 @@
-import * as ReactDOM from 'react-dom';
-import * as rp from 'request-promise';
import { Docs } from '../client/documents/Documents';
import "./ImageUpload.scss";
import React = require('react');
-import { DocServer } from '../client/DocServer';
import { observer } from 'mobx-react';
import { observable, action, computed } from 'mobx';
import { Utils, emptyPath, returnFalse, emptyFunction, returnOne, returnZero, returnTrue, returnEmptyFilter } from '../Utils';
-import { Networking } from '../client/Network';
import { Doc, Opt } from '../fields/Doc';
import { Cast, FieldValue } from '../fields/Types';
import { listSpec } from '../fields/Schema';
-import { List } from '../fields/List';
-import { Scripting } from '../client/util/Scripting';
import MainViewModal from '../client/views/MainViewModal';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { nullAudio } from '../fields/URLField';
import { Transform } from '../client/util/Transform';
import { DocumentView } from '../client/views/nodes/DocumentView';
import { MobileInterface } from './MobileInterface';
-
-export interface ImageUploadProps {
- Document: Doc;
-}
-
-// const onPointerDown = (e: React.TouchEvent) => {
-// let imgInput = document.getElementById("input_image_file");
-// if (imgInput) {
-// imgInput.click();
-// }
-// }
-const inputRef = React.createRef<HTMLInputElement>();
+import { DictationOverlay } from '../client/views/DictationOverlay';
+import RichTextMenu from '../client/views/nodes/formattedText/RichTextMenu';
+import { ContextMenu } from '../client/views/ContextMenu';
@observer
export class AudioUpload extends React.Component {
- @observable error: string = "";
- @observable status: string = "";
- @observable nm: string = "Choose files";
- @observable process: string = "";
- @observable public _audioCol: Doc = FieldValue(Cast(Docs.Create.FreeformDocument([Cast(Docs.Create.AudioDocument(nullAudio, { title: "mobile audio", _width: 500, _height: 100 }), Doc) as Doc], { title: "mobile audio", _fitToBox: true, boxShadow: "0 0" }), Doc)) as Doc;
-
+ @observable public _audioCol: Doc = FieldValue(Cast(Docs.Create.FreeformDocument([Cast(Docs.Create.AudioDocument(nullAudio, { title: "mobile audio", _width: 500, _height: 100 }), Doc) as Doc], { title: "mobile audio", _width: 300, _height: 300, _fitToBox: true, boxShadow: "0 0" }), Doc)) as Doc;
+ /**
+ * Handles the onclick functionality for the 'Restart' button
+ * Resets the document to its default view
+ */
@action
clearUpload = () => {
for (let i = 1; i < 8; i++) {
this.setOpacity(i, "0.2");
}
- this._audioCol = FieldValue(Cast(Docs.Create.FreeformDocument([Cast(Docs.Create.AudioDocument(nullAudio, { title: "mobile audio", _width: 500, _height: 100 }), Doc) as Doc], { title: "mobile audio", _fitToBox: true, boxShadow: "0 0" }), Doc)) as Doc;
+ this._audioCol = FieldValue(Cast(
+ Docs.Create.FreeformDocument(
+ [Cast(Docs.Create.AudioDocument(nullAudio, {
+ title: "mobile audio",
+ _width: 500,
+ _height: 100
+ }), Doc) as Doc], { title: "mobile audio", _width: 300, _height: 300, _fitToBox: true, boxShadow: "0 0" }), Doc)) as Doc;
}
+ /**
+ * Handles the onClick of the 'Close' button
+ * Reset upload interface and toggle audio
+ */
closeUpload = () => {
this.clearUpload();
MobileInterface.Instance.toggleAudio();
}
+ /**
+ * Handles the on click of the 'Upload' button.
+ * Pushing the audio doc onto Dash Web through the right side bar
+ */
+ uploadAudio = () => {
+ const audioRightSidebar = Cast(Doc.UserDoc().rightSidebarCollection, Doc) as Doc;
+ const audioDoc = this._audioCol;
+ const data = Cast(audioRightSidebar.data, listSpec(Doc));
+ for (let i = 1; i < 8; i++) {
+ setTimeout(() => this.setOpacity(i, "1"), i * 200);
+ }
+ if (data) {
+ data.push(audioDoc);
+ }
+ // Resets uploader after 3 seconds
+ setTimeout(this.clearUpload, 3000);
+ }
+
+ // Returns the upload audio menu
private get uploadInterface() {
return (
<>
+ <ContextMenu />
+ <DictationOverlay />
+ <div style={{ display: "none" }}><RichTextMenu key="rich" /></div>
<div className="closeUpload" onClick={() => this.closeUpload()}>
<FontAwesomeIcon icon="window-close" size={"lg"} />
</div>
@@ -66,10 +82,10 @@ export class AudioUpload extends React.Component {
Document={this._audioCol}
DataDoc={undefined}
LibraryPath={emptyPath}
- addDocument={returnFalse}
+ addDocument={undefined}
addDocTab={returnFalse}
pinToPres={emptyFunction}
- rootSelected={returnFalse}
+ rootSelected={returnTrue}
removeDocument={undefined}
docFilters={returnEmptyFilter}
onClick={undefined}
@@ -108,30 +124,14 @@ export class AudioUpload extends React.Component {
);
}
- setOpacity = (i: number, o: string) => {
- const slab = document.getElementById("slab0" + i);
+ // Handles the setting of the loading bar
+ setOpacity = (index: number, opacity: string) => {
+ const slab = document.getElementById("slab0" + index);
if (slab) {
- console.log(slab?.id);
- slab.style.opacity = o;
+ slab.style.opacity = opacity;
}
}
- // Pushing the audio doc onto Dash Web through the right side bar
- uploadAudio = () => {
- console.log("uploading");
- const audioRightSidebar = Cast(Doc.UserDoc().rightSidebarCollection, Doc) as Doc;
- const audioDoc = this._audioCol;
- const data = Cast(audioRightSidebar.data, listSpec(Doc));
- for (let i = 1; i < 8; i++) {
- setTimeout(() => this.setOpacity(i, "1"), i * 200);
- }
- if (data) {
- data.push(audioDoc);
- }
-
- setTimeout(this.clearUpload, 3000);
- }
-
@observable private dialogueBoxOpacity = 1;
@observable private overlayOpacity = 0.4;
diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx
index 6a5a2dd5b..5ea626d52 100644
--- a/src/mobile/ImageUpload.tsx
+++ b/src/mobile/ImageUpload.tsx
@@ -1,4 +1,3 @@
-import * as ReactDOM from 'react-dom';
import * as rp from 'request-promise';
import { Docs } from '../client/documents/Documents';
import "./ImageUpload.scss";
@@ -12,49 +11,38 @@ import { Doc, Opt } from '../fields/Doc';
import { Cast } from '../fields/Types';
import { listSpec } from '../fields/Schema';
import { List } from '../fields/List';
-import { Scripting } from '../client/util/Scripting';
import MainViewModal from '../client/views/MainViewModal';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { MobileInterface } from './MobileInterface';
-import { CurrentUserUtils } from '../client/util/CurrentUserUtils';
export interface ImageUploadProps {
- Document: Doc;
+ Document: Doc; // Target document for upload (upload location)
}
-// const onPointerDown = (e: React.TouchEvent) => {
-// let imgInput = document.getElementById("input_image_file");
-// if (imgInput) {
-// imgInput.click();
-// }
-// }
const inputRef = React.createRef<HTMLInputElement>();
@observer
export class Uploader extends React.Component<ImageUploadProps> {
@observable error: string = "";
- @observable status: string = "";
- @observable nm: string = "Choose files";
- @observable process: string = "";
+ @observable nm: string = "Choose files"; // Text of 'Choose Files' button
+ @observable process: string = ""; // Current status of upload
onClick = async () => {
try {
const col = this.props.Document;
await Docs.Prototypes.initialize();
const imgPrev = document.getElementById("img_preview");
- // Slab 1
- this.setOpacity(1, "1");
+ this.setOpacity(1, "1"); // Slab 1
if (imgPrev) {
const files: FileList | null = inputRef.current!.files;
- // Slab 2
- this.setOpacity(2, "1");
+ this.setOpacity(2, "1"); // Slab 2
if (files && files.length !== 0) {
this.process = "Uploading Files";
for (let index = 0; index < files.length; ++index) {
const file = files[index];
const res = await Networking.UploadFilesToServer(file);
- // Slab 3
- this.setOpacity(3, "1");
+ this.setOpacity(3, "1"); // Slab 3
+ // For each item that the user has selected
res.map(async ({ result }) => {
const name = file.name;
if (result instanceof Error) {
@@ -62,16 +50,17 @@ export class Uploader extends React.Component<ImageUploadProps> {
}
const path = Utils.prepend(result.accessPaths.agnostic.client);
let doc = null;
- console.log("type: " + file.type);
+ // Case 1: File is a video
if (file.type === "video/mp4") {
doc = Docs.Create.VideoDocument(path, { _nativeWidth: 400, _width: 400, title: name });
+ // Case 2: File is a PDF document
} else if (file.type === "application/pdf") {
doc = Docs.Create.PdfDocument(path, { _nativeWidth: 400, _width: 400, title: name });
+ // Case 3: File is another document type (most likely Image)
} else {
doc = Docs.Create.ImageDocument(path, { _nativeWidth: 400, _width: 400, title: name });
}
- // Slab 4
- this.setOpacity(4, "1");
+ this.setOpacity(4, "1"); // Slab 4
const res = await rp.get(Utils.prepend("/getUserDocumentId"));
if (!res) {
throw new Error("No user id returned");
@@ -79,32 +68,27 @@ export class Uploader extends React.Component<ImageUploadProps> {
const field = await DocServer.GetRefField(res);
let pending: Opt<Doc>;
if (field instanceof Doc) {
- // if (col === Cast(Doc.UserDoc().rightSidebarCollection, Doc) as Doc) {
- // pending = await Cast(field.rightSidebarCollection, Doc);
- // }
pending = col;
- //pending = await Cast(field.col, Doc);
}
if (pending) {
const data = await Cast(pending.data, listSpec(Doc));
if (data) data.push(doc);
else pending.data = new List([doc]);
- this.status = "finished";
this.setOpacity(5, "1"); // Slab 5
this.process = "File " + (index + 1).toString() + " Uploaded";
this.setOpacity(6, "1"); // Slab 6
- this.setOpacity(7, "1"); // Slab 7
}
- console.log("i: " + index + 1);
- console.log("l: " + files.length);
if ((index + 1) === files.length) {
this.process = "Uploads Completed";
+ this.setOpacity(7, "1"); // Slab 7
}
});
}
+ // Case in which the user pressed upload and no files were selected
} else {
this.process = "No file selected";
}
+ // Three seconds after upload the menu will reset
setTimeout(this.clearUpload, 3000);
}
} catch (error) {
@@ -117,14 +101,13 @@ export class Uploader extends React.Component<ImageUploadProps> {
const files: FileList | null = inputRef.current!.files;
await files;
if (files && files.length === 1) {
- console.log(files);
this.nm = files[0].name;
} else if (files && files.length > 1) {
- console.log(files.length);
this.nm = files.length.toString() + " files selected";
}
}
+ // Loops through load icons, and resets buttons
@action
clearUpload = () => {
for (let i = 1; i < 8; i++) {
@@ -136,23 +119,21 @@ export class Uploader extends React.Component<ImageUploadProps> {
inputRef.current.value = "";
}
this.process = "";
- console.log(inputRef.current!.files);
}
+ // Clears the upload and closes the upload menu
closeUpload = () => {
this.clearUpload();
MobileInterface.Instance.toggleUpload();
}
- setOpacity = (i: number, o: string) => {
- const slab = document.getElementById("slab" + i);
- if (slab) {
- console.log(slab?.id);
- slab.style.opacity = o;
- }
+ // Handles the setting of the loading bar
+ setOpacity = (index: number, opacity: string) => {
+ const slab = document.getElementById("slab" + index);
+ if (slab) slab.style.opacity = opacity;
}
-
+ // Returns the upload interface for mobile
private get uploadInterface() {
return (
<div className="imgupload_cont">
diff --git a/src/mobile/MobileHome.scss b/src/mobile/MobileHome.scss
deleted file mode 100644
index e1566b622..000000000
--- a/src/mobile/MobileHome.scss
+++ /dev/null
@@ -1,101 +0,0 @@
-$navbar-height: 120px;
-$pathbar-height: 50px;
-
-* {
- margin: 0px;
- padding: 0px;
- box-sizing: border-box;
- font-family: "Open Sans";
-}
-
-.homeContainer {
- position: relative;
- top: 200px;
- overflow: scroll;
- width: 100%;
- left: 0;
- height: calc(100% - 120px);
- overflow-y: scroll;
-}
-
-.homeButton {
- width: 96%;
- margin-left: 2.5%;
- height: 250px;
- border-radius: 30px;
- margin-top: 15px;
- margin-bottom: 15px;
-}
-
-.iconRight {
- position: absolute;
- width: 50%;
- height: 80px;
- transform: translate(0, 50%);
- right: 0px;
- text-align: center;
- font-size: 80;
-}
-
-.iconLeft {
- position: absolute;
- width: 50%;
- height: 80px;
- transform: translate(0%, 50%);
- left: 0px;
- text-align: center;
- font-size: 80;
-}
-
-.textLeft {
- position: absolute;
- width: 50%;
- left: 0px;
- font-size: 40px;
- text-align: left;
- margin-left: 110px;
- margin-top: 40px;
- font-family: sans-serif;
- font-weight: bold;
-}
-
-.textRight {
- position: absolute;
- width: 50%;
- right: 0px;
- font-size: 40px;
- text-align: right;
- margin-right: 110px;
- margin-top: 40px;
- font-family: sans-serif;
- font-weight: bold;
-}
-
-.menuView {
- position: absolute;
- top: 135px;
- left: 50%;
- transform: translate(-50%, 0%);
- display: flex;
-}
-
-.iconView {
- height: 60px;
- width: 60px;
- background-color: darkgray;
- border-radius: 5px;
- border-style: solid;
- border-width: 2px;
- border-color: black;
-}
-
-.listView {
- height: 60px;
- width: 60px;
- margin-left: 20;
- background-color: darkgray;
- border-radius: 5px;
- border-style: solid;
- border-width: 2px;
- border-color: black;
-} \ No newline at end of file
diff --git a/src/mobile/MobileInterface.scss b/src/mobile/MobileInterface.scss
index 86b043590..ee39d4f50 100644
--- a/src/mobile/MobileInterface.scss
+++ b/src/mobile/MobileInterface.scss
@@ -1,36 +1,444 @@
-.mobileInterface-inkInterfaceButtons {
- position: absolute;
- top: 0px;
- display: flex;
- justify-content: space-between;
- width: 100%;
- z-index: 9999;
- height: 50px;
+$navbar-height: 120px;
+$pathbar-height: 50px;
- .mobileInterface-button {
- height: 100%;
+@media only screen and (max-device-width: 480px) {
+ * {
+ margin: 0px;
+ padding: 0px;
+ box-sizing: border-box;
+ font-family: sans-serif;
}
}
+body {
+ overflow: hidden;
+}
+
.mobileInterface-container {
height: 100%;
position: relative;
touch-action: none;
width: 100%;
- -webkit-touch-callout:none;
- -webkit-user-select:none;
- -khtml-user-select:none;
- -moz-user-select:none;
- -ms-user-select:none;
- user-select:none;
- -webkit-tap-highlight-color:rgba(0,0,0,0);
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+
+// Topbar of Dash Mobile
+.navbar {
+ position: fixed;
+ top: 0px;
+ left: 0px;
+ width: 100vw;
+ height: $navbar-height;
+ background-color: whitesmoke;
+ z-index: 150;
+
+ .cover {
+ position: absolute;
+ right: 0px;
+ top: 0px;
+ height: 120px;
+ width: 120px;
+ background-color: whitesmoke;
+ z-index: 200;
+ }
+
+ .toggle-btn {
+ position: absolute;
+ right: 20px;
+ top: 30px;
+ height: 70px;
+ width: 70px;
+ transition: all 400ms ease-in-out 200ms;
+ z-index: 180;
+ }
+
+ .background {
+ position: absolute;
+ right: 0px;
+ top: 0px;
+ height: 120px;
+ width: 120px;
+ //border: 1px solid black;
+ }
+
+ .background.active {
+ background-color: lightgrey;
+ }
+
+ .toggle-btn-home {
+ right: -200px;
+ }
+
+ .header {
+ position: absolute;
+ top: 50%;
+ top: calc(9px + 50%);
+ right: 50%;
+ transform: translate(50%, -50%);
+ font-size: 40;
+ font-weight: 700;
+ text-align: center;
+ user-select: none;
+ text-transform: uppercase;
+ font-family: Arial, Helvetica, sans-serif;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ direction: ltr;
+ width: 600px;
+ }
+
+ .toggle-btn span {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ width: 70%;
+ height: 4px;
+ background: black;
+ transition: all 200ms ease;
+ z-index: 180;
+ }
+
+ .toggle-btn span:nth-child(1) {
+ transition: top 200ms ease-in-out;
+ top: 30%;
+ }
+
+ .toggle-btn span:nth-child(3) {
+ transition: top 200ms ease-in-out;
+ top: 70%;
+ }
+
+ .toggle-btn.active {
+ transition: transform 200ms ease-in-out 200ms;
+ transform: rotate(135deg);
+ }
+
+ .toggle-btn.active span:nth-child(1) {
+ top: 50%;
+ }
+
+ .toggle-btn.active span:nth-child(2) {
+ transform: translate(-50%, -50%) rotate(90deg);
+ }
+
+ .toggle-btn.active span:nth-child(3) {
+ top: 50%;
+ }
+}
+
+.sidebar {
+ position: fixed;
+ top: 120px;
+ opacity: 0;
+ right: -100%;
+ width: 80%;
+ height: calc(80% - (120px));
+ z-index: 101;
+ background-color: whitesmoke;
+ transition: all 400ms ease 50ms;
+ padding: 20px;
+ box-shadow: 0 0 5px 5px grey;
+
+ .item {
+ width: 100%;
+ padding: 13px 12px;
+ border-bottom: 1px solid rgba(200, 200, 200, 0.7);
+ font-family: Arial, Helvetica, sans-serif;
+ font-style: normal;
+ font-weight: normal;
+ user-select: none;
+ display: inline-flex;
+ font-size: 35px;
+ text-transform: uppercase;
+ color: black;
+ }
+
+ .ink:focus {
+ outline: 1px solid blue;
+ }
+
+ .sidebarButtons {
+ top: 80px;
+ position: relative;
+ }
+}
+
+
+
+
+
+
+.blanket {
+ position: fixed;
+ top: 120px;
+ opacity: 0.5;
+ right: -100%;
+ width: 100%;
+ height: calc(100% - (120px));
+ z-index: 101;
+ background-color: grey;
+ padding: 20px;
+}
+
+.blanket.active {
+ position: absolute;
+ right: 0%;
+ z-index: 100;
+}
+
+.home {
+ position: absolute;
+ top: 30px;
+ left: 30px;
+ font-size: 60;
+ user-select: none;
+ text-transform: uppercase;
+ font-family: Arial, Helvetica, sans-serif;
+ z-index: 200;
}
-.mobileInterface-background {
+.item-type {
+ display: inline;
+ text-transform: lowercase;
+ margin-left: 20px;
+ font-size: 35px;
+ font-style: italic;
+ color: rgb(28, 28, 28);
+}
+
+.item-title {
+ max-width: 70%;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.right {
+ margin-left: 20px;
+ z-index: 200;
+}
+
+.open {
+ right: 20px;
+ font-size: 35;
+ position: absolute;
+}
+
+.left {
+ width: 100%;
height: 100%;
+}
+
+
+
+.sidebar.active {
+ position: absolute;
+ right: 0%;
+ opacity: 1;
+ z-index: 101;
+}
+
+.back {
+ position: absolute;
+ left: 42px;
+ top: 0;
+ background: #1a1a1a;
+ width: 50px;
+ height: 100%;
+ display: flex;
+ justify-content: center;
+ text-align: center;
+ flex-direction: column;
+ align-items: center;
+ border-radius: 10px;
+ font-size: 25px;
+ user-select: none;
+ z-index: 100;
+}
+
+.pathbar {
+ position: fixed;
+ top: 118px;
+ left: 0px;
+ background: #1a1a1a;
+ z-index: 120;
+ border-radius: 0px;
width: 100%;
+ height: 80px;
+ overflow: hidden;
+
+ .pathname {
+ position: relative;
+ font-size: 25;
+ top: 50%;
+ width: 86%;
+ left: 12%;
+ color: whitesmoke;
+ transform: translate(0%, -50%);
+ z-index: 20;
+ font-family: sans-serif;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ direction: rtl;
+ text-align: left;
+ text-transform: uppercase;
+ }
+
+ .scrollmenu {
+ overflow: auto;
+ width: 100%;
+ height: 100%;
+ white-space: nowrap;
+ display: inline-flex;
+ }
+
+ .hidePath {
+ position: absolute;
+ height: 100%;
+ width: 200px;
+ left: 0px;
+ top: 0px;
+ background-image: linear-gradient(to right, #1a1a1a, rgba(0, 0, 0, 0));
+ text-align: center;
+ user-select: none;
+ z-index: 99;
+ pointer-events: none;
+ }
+
+ .pathbarItem {
+ position: relative;
+ display: flex;
+ align-items: center;
+ color: whitesmoke;
+ text-align: center;
+ justify-content: center;
+ user-select: none;
+ transform: translate(100px, 0px);
+ font-size: 30px;
+ padding: 10px;
+ text-transform: uppercase;
+
+ .pathbarText {
+ font-family: sans-serif;
+ text-align: center;
+ height: 50px;
+ padding: 10px;
+ font-size: 30px;
+ border-radius: 10px;
+ text-transform: uppercase;
+ margin-left: 20px;
+ position: relative;
+ }
+
+ .pathIcon {
+ transform: translate(0px, 0px);
+ position: relative;
+ }
+ }
+}
+
+
+/**
+* docButton appears at the bottom of mobile document
+* Buttons include: pin to presentation, download, upload, reload
+*/
+.docButton {
position: relative;
- touch-action: none;
- background-color: pink;
+ width: 100px;
+ display: flex;
+ height: 100px;
+ font-size: 70px;
+ text-align: center;
+ border: 3px solid black;
+ margin: 20px;
+ z-index: 100;
+ border-radius: 100%;
+ justify-content: center;
+ flex-direction: column;
+ align-items: center;
+}
+
+.docButtonContainer {
+ top: 80%;
+ position: absolute;
+ display: flex;
+ transform: translate(-50%, 0);
+ left: 50%;
+ z-index: 100;
}
+
+.toolbar {
+ left: 50%;
+ transform: translate(-50%);
+ position: absolute;
+ height: max-content;
+ top: 0px;
+ border-radius: 20px;
+ background-color: lightgrey;
+ opacity: 0;
+ transition: all 400ms ease 50ms;
+}
+
+.toolbar.active {
+ display: inline-block;
+ width: 300px;
+ padding: 5px;
+ opacity: 1;
+ height: max-content;
+ top: -450px;
+}
+
+.colorSelector {
+ position: absolute;
+ top: 550px;
+ left: 300px;
+ transform: translate(-50%, 0);
+ z-index: 100;
+ display: inline-flex;
+ width: max-content;
+ height: max-content;
+ pointer-events: all;
+ font-size: 90px;
+}
+
+// Menu buttons for toggling between list and icon view
+.homeSwitch {
+ position: fixed;
+ top: 212;
+ right: 36px;
+ display: inline-flex;
+ width: max-content;
+ z-index: 99;
+ height: 70px;
+
+ .list {
+ width: 70px;
+ height: 70px;
+ margin: 5;
+ padding: 10;
+ align-items: center;
+ text-align: center;
+ font-size: 50;
+ border-style: solid;
+ border-width: 3;
+ border-color: black;
+ background: whitesmoke;
+ align-self: center;
+ border-radius: 10px;
+ }
+
+ .list.active {
+ color: darkred;
+ border-color: darkred;
+ }
+} \ No newline at end of file
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index 8cec03897..a49bfb9b1 100644
--- a/src/mobile/MobileInterface.tsx
+++ b/src/mobile/MobileInterface.tsx
@@ -9,43 +9,33 @@ import {
faThumbtack, faTree, faTv, faBook, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faHome, faLongArrowAltLeft, faBars, faTh, faChevronLeft
} from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable, reaction } from 'mobx';
+import { action, computed, observable, reaction, trace } 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';
import { emptyFunction, emptyPath, returnEmptyString, returnFalse, returnOne, returnTrue, returnZero, returnEmptyFilter } from '../Utils';
-import { DocServer } from '../client/DocServer';
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';
import "./MobileInterface.scss";
-import "./MobileMenu.scss";
-import "./MobileHome.scss";
import "./ImageUpload.scss";
import "./AudioUpload.scss";
-import { DocumentManager } from '../client/util/DocumentManager';
import SettingsManager from '../client/util/SettingsManager';
import { Uploader } from "./ImageUpload";
import { DockedFrameRenderer } from '../client/views/collections/CollectionDockingView';
import { InkTool } from '../fields/InkField';
-import { listSpec } from '../fields/Schema';
-import { nullAudio } from '../fields/URLField';
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, undoBatch } from "../client/util/UndoManager";
-import { MainView } from "../client/views/MainView";
+import { UndoManager } from "../client/util/UndoManager";
import { List } from "../fields/List";
import { AudioUpload } from "./AudioUpload";
import { Cast, FieldValue } from '../fields/Types';
-import { CollectionView } from '../client/views/collections/CollectionView';
-import { InkingStroke } from '../client/views/InkingStroke';
import RichTextMenu from "../client/views/nodes/formattedText/RichTextMenu";
+import { AudioBox } from "../client/views/nodes/AudioBox";
+import { Compute } from "google-auth-library";
library.add(faTasks, faReply, faQuoteLeft, faHandPointLeft, faFolderOpen, faAngleDoubleLeft, 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,
@@ -81,11 +71,13 @@ export class MobileInterface extends React.Component {
@action
componentDidMount = () => {
- Doc.UserDoc().activeMobile = this._homeDoc;
+ // if the home menu is in list view -> adjust the menu toggle appropriately
this._homeDoc._viewType === "stacking" ? this.menuListView = true : this.menuListView = false;
- Doc.SetSelectedTool(InkTool.None);
- this.switchCurrentView((userDoc: Doc) => this._homeDoc);
+ Doc.SetSelectedTool(InkTool.None); // ink should intially be set to none
+ Doc.UserDoc().activeMobile = this._homeDoc; // active mobile set to home
+ AudioBox.Enabled = true;
+ // remove double click to avoid mobile zoom in
document.removeEventListener("dblclick", this.onReactDoubleClick);
document.addEventListener("dblclick", this.onReactDoubleClick);
}
@@ -102,13 +94,19 @@ export class MobileInterface extends React.Component {
// Switch the mobile view to the given doc
@action
- switchCurrentView = (doc: (userDoc: Doc) => Doc, renderView?: () => JSX.Element, onSwitch?: () => void) => {
+ switchCurrentView = (doc: Doc, renderView?: () => JSX.Element, onSwitch?: () => void) => {
if (!this.userDoc) return;
-
- Doc.UserDoc().activeMobile = doc(this.userDoc);
+ if (this._activeDoc === this._homeDoc) {
+ this._parents.push(this._activeDoc);
+ this._homeMenu = false;
+ }
+ this._activeDoc = doc;
+ Doc.UserDoc().activeMobile = doc;
onSwitch && onSwitch();
this.renderView = renderView;
+ // Ensures that switching to home is not registed
+ UndoManager.undoStack.length = 0;
}
// For toggling the hamburger menu
@@ -119,21 +117,10 @@ export class MobileInterface extends React.Component {
* Method called when 'Library' button is pressed on the home screen
*/
switchToLibrary = async () => {
- this._parents.push(this._activeDoc);
- this.switchCurrentView((userDoc: Doc) => this._library);
- this._activeDoc = this._library;
+ this.switchCurrentView(this._library);
this._homeMenu = false;
this.toggleSidebar();
//setTimeout(this.toggleSidebar, 300);
-
- }
-
- openWorkspaces = () => {
- this._parents.push(this._activeDoc);
- this.switchCurrentView((userDoc: Doc) => this._library);
- this._activeDoc = this._library;
- this._homeMenu = false;
- this.sidebarActive = true;
}
/**
@@ -141,41 +128,38 @@ export class MobileInterface extends React.Component {
*/
back = () => {
const header = document.getElementById("header") as HTMLElement;
- const doc = Cast(this._parents.pop(), Doc) as Doc;
-
+ const doc = Cast(this._parents.pop(), Doc) as Doc; // Parent document
+ // Case 1: Parent document is 'workspaces'
if (doc === Cast(this._library, Doc) as Doc) {
this._child = null;
- this.userDoc.activeMobile = this._library;
+ this.switchCurrentView(this._library);
+ // Case 2: Parent document is the 'home' menu (root node)
} else if (doc === Cast(this._homeDoc, Doc) as Doc) {
this._homeMenu = true;
this._parents = [];
- this._activeDoc = this._homeDoc;
this._child = null;
- this.switchCurrentView((userDoc: Doc) => this._homeDoc);
+ this.switchCurrentView(this._homeDoc);
+ // Case 3: Parent document is any document
} else {
if (doc) {
this._child = doc;
- this.switchCurrentView((userDoc: Doc) => doc);
+ this.switchCurrentView(doc);
this._homeMenu = false;
header.textContent = String(doc.title);
}
}
- if (doc) {
- this._activeDoc = doc;
- }
- this._ink = false;
+ this._ink = false; // turns ink off
}
/**
- * Return 'Home", which implies returning to 'Home' buttons
+ * Return 'Home", which implies returning to 'Home' menu buttons
*/
returnHome = () => {
if (!this._homeMenu || this.sidebarActive) {
this._homeMenu = true;
this._parents = [];
- this._activeDoc = this._homeDoc;
this._child = null;
- this.switchCurrentView((userDoc: Doc) => this._homeDoc);
+ this.switchCurrentView(this._homeDoc);
}
if (this.sidebarActive) {
this.toggleSidebar();
@@ -187,8 +171,7 @@ export class MobileInterface extends React.Component {
*/
returnMain = () => {
this._parents = [this._homeDoc];
- this._activeDoc = this._library;
- this.switchCurrentView((userDoc: Doc) => this._library);
+ this.switchCurrentView(this._library);
this._homeMenu = false;
this._child = null;
}
@@ -196,7 +179,7 @@ export class MobileInterface extends React.Component {
/**
* DocumentView for graphic display of all documents
*/
- displayWorkspaces = () => {
+ @computed get displayWorkspaces() {
if (this.mainContainer) {
const backgroundColor = () => "white";
return (
@@ -245,32 +228,32 @@ export class MobileInterface extends React.Component {
* Navigates to the given doc and updates the sidebar.
* @param doc: doc for which the method is called
*/
- @undoBatch
handleClick = async (doc: Doc) => {
const children = DocListCast(doc.data);
if (doc.type !== "collection" && this.sidebarActive) {
this._parents.push(this._activeDoc);
- this._activeDoc = doc;
- this.switchCurrentView((userDoc: Doc) => doc);
+ this.switchCurrentView(doc);
this._homeMenu = false;
this.toggleSidebar();
}
- else if (doc.type === "collection" && children.length === 0) this.openFromSidebar(doc);
else {
this._parents.push(this._activeDoc);
- this._activeDoc = doc;
- this.switchCurrentView((userDoc: Doc) => doc);
+ this.switchCurrentView(doc);
this._homeMenu = false;
this._child = doc;
}
}
+ /**
+ * Called when an item in the library is clicked and should
+ * be opened (open icon on RHS of all menu items)
+ * @param doc doc to be opened
+ */
openFromSidebar = (doc: Doc) => {
this._parents.push(this._activeDoc);
- this._activeDoc = doc;
- this.switchCurrentView((userDoc: Doc) => doc);
+ this.switchCurrentView(doc);
this._homeMenu = false;
- this._child = doc; //?
+ this._child = doc;
this.toggleSidebar();
}
@@ -355,16 +338,14 @@ export class MobileInterface extends React.Component {
// Handles when user clicks on a document in the pathbar
handlePathClick = (doc: Doc, index: number) => {
if (doc === this._library) {
- this._activeDoc = doc;
this._child = null;
- this.switchCurrentView((userDoc: Doc) => doc);
+ this.switchCurrentView(doc);
this._parents.length = index;
} else if (doc === this._homeDoc) {
this.returnHome();
} else {
- this._activeDoc = doc;
this._child = doc;
- this.switchCurrentView((userDoc: Doc) => doc);
+ this.switchCurrentView(doc);
this._parents.length = index;
}
}
@@ -388,12 +369,12 @@ export class MobileInterface extends React.Component {
</div>
);
}
-
+ // stores workspace documents as 'workspaces' variable
let workspaces = Cast(this.userDoc.myWorkspaces, Doc) as Doc;
if (this._child) {
workspaces = this._child;
}
-
+ // returns a list of navbar buttons as 'buttons'
const buttons = DocListCast(workspaces.data).map((doc: Doc, index: any) => {
if (doc.type !== "ink") {
return (
@@ -455,7 +436,7 @@ export class MobileInterface extends React.Component {
}
/**
- * Handles the Create New Workspace button in the menu (taken from MainView.tsx)
+ * Handles the 'Create New Workspace' button in the menu (taken from MainView.tsx)
*/
@action
createNewWorkspace = async (id?: string) => {
@@ -464,8 +445,7 @@ export class MobileInterface extends React.Component {
const freeformOptions: DocumentOptions = {
x: 0,
y: 400,
- title: "Collection " + workspaceCount,
- _LODdisable: true
+ title: "Collection " + workspaceCount
};
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");
@@ -477,27 +457,12 @@ export class MobileInterface extends React.Component {
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();
}
- // Button for uploading mobile audio
- 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>;
- }
- }
-
// Button for switching between pen and ink mode
@action
onSwitchInking = () => {
@@ -526,9 +491,9 @@ export class MobileInterface extends React.Component {
}
}
-
- undo = () => {
- if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc && this._activeDoc.title !== "WORKSPACES") {
+ // DocButton that uses UndoManager and handles the opacity change if CanUndo is true
+ @computed get undo() {
+ if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc && this._activeDoc !== this.userDoc.rightSidebarCollection && this._activeDoc.title !== "WORKSPACES") {
return (<>
<div className="docButton"
style={{ backgroundColor: "black", color: "white", fontSize: "60", opacity: UndoManager.CanUndo() ? "1" : "0.4", }}
@@ -544,8 +509,9 @@ export class MobileInterface extends React.Component {
}
}
- redo = () => {
- if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc && this._activeDoc.title !== "WORKSPACES") {
+ // DocButton that uses UndoManager and handles the opacity change if CanRedo is true
+ @computed get redo() {
+ if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc && this._activeDoc !== this.userDoc.rightSidebarCollection && this._activeDoc.title !== "WORKSPACES") {
return (<>
<div className="docButton"
style={{ backgroundColor: "black", color: "white", fontSize: "60", opacity: UndoManager.CanRedo() ? "1" : "0.4", }}
@@ -561,8 +527,8 @@ export class MobileInterface extends React.Component {
}
}
- // Button for switching into ink mode
- drawInk = () => {
+ // DocButton for switching into ink mode
+ @computed get drawInk() {
if (this._activeDoc._viewType === "docking") {
return (
<>
@@ -577,23 +543,20 @@ export class MobileInterface extends React.Component {
}
}
- // Mobile doc button for uploading
- upload = () => {
- if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc) {
- return (
- <>
- <div className="docButton"
- id="uploadButton"
- title={"uploadFile"}
- onClick={this.toggleUpload}>
- <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="upload"
- />
- </div>
- </>);
+ // DocButton: Button that appears on the bottom of the screen to initiate image upload
+ uploadImageButton = () => {
+ if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc && this._activeDoc._viewType !== "docking" && this._activeDoc.title !== "WORKSPACES") {
+ return <div className="docButton"
+ id="imageButton"
+ title={Doc.isDocPinned(this._activeDoc) ? "Pen on" : "Pen off"}
+ onClick={this.toggleUpload}>
+ <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="upload"
+ />
+ </div>;
}
}
- // Button to download images on the mobile
+ // DocButton to download images on the mobile
downloadDocument = () => {
if (this._activeDoc.type === "image" || this._activeDoc.type === "pdf" || this._activeDoc.type === "video") {
const url = this._activeDoc["data-path"]?.toString();
@@ -602,7 +565,6 @@ export class MobileInterface extends React.Component {
style={{ backgroundColor: "white", color: "black" }}
onClick={e => {
window.open(url);
- console.log(url);
}}>
<FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="download"
/>
@@ -610,32 +572,7 @@ export class MobileInterface extends React.Component {
}
}
- // Mobile audio doc
- 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;
- if (audioDoc) {
- this._activeDoc = audioDoc;
- this.switchCurrentView((userDoc: Doc) => audioDoc);
- this._homeMenu = false;
- }
- }
-
- // // Pushing the audio doc onto Dash Web through the right side bar
- // uploadAudio = () => {
- // const audioRightSidebar = Cast(Doc.UserDoc().rightSidebarCollection, Doc) as Doc;
- // const audioDoc = this._activeDoc;
- // const data = Cast(audioRightSidebar.data, listSpec(Doc));
-
- // if (data) {
- // data.push(audioDoc);
- // }
- // }
-
- // Button for pinning images to presentation
+ // DocButton for pinning images to presentation
pinToPresentation = () => {
// Only making button available if it is an image
if (!(this._activeDoc.type === "collection" || this._activeDoc.type === "presentation")) {
@@ -681,18 +618,13 @@ export class MobileInterface extends React.Component {
this._homeDoc._viewType = "masonry";
this._homeDoc.columnWidth = 300;
const menuButtons = DocListCast(this._homeDoc.data);
- console.log('hello');
menuButtons.map((doc: Doc, index: any) => {
- console.log(index);
const buttonData = DocListCast(doc.data);
buttonData[1]._nativeWidth = 0.1;
buttonData[1]._width = 0.1;
buttonData[1]._dimMagnitude = 0;
buttonData[1]._opacity = 0;
- console.log(buttonData);
- console.log(doc._nativeWidth);
doc._nativeWidth = 400;
- console.log(doc._nativeWidth);
});
}
}
@@ -704,30 +636,22 @@ export class MobileInterface extends React.Component {
this._homeDoc._viewType = "stacking";
this.menuListView = true;
const menuButtons = DocListCast(this._homeDoc.data);
- console.log('hello');
menuButtons.map((doc: Doc, index: any) => {
const buttonData = DocListCast(doc.data);
buttonData[1]._nativeWidth = 450;
buttonData[1]._dimMagnitude = 2;
buttonData[1]._opacity = 1;
- console.log(doc._nativeWidth);
doc._nativeWidth = 900;
- console.log(doc._nativeWidth);
});
}
}
// For setting up the presentation document for the home menu
setupDefaultPresentation = () => {
- if (this._activeDoc.title !== "Presentation") {
- this._parents.push(this._activeDoc);
- }
-
const presentation = Cast(Doc.UserDoc().activePresentation, Doc) as Doc;
if (presentation) {
- this._activeDoc = presentation;
- this.switchCurrentView((userDoc: Doc) => presentation);
+ this.switchCurrentView(presentation);
this._homeMenu = false;
}
}
@@ -736,10 +660,11 @@ export class MobileInterface extends React.Component {
@action
toggleUpload = () => this.imageUploadActive = !this.imageUploadActive
- // For toggling image upload pop up
+ // For toggling audio record and dictate pop up
@action
toggleAudio = () => this.audioUploadActive = !this.audioUploadActive
+ // Button for toggling the upload pop up in a collection
@action
toggleUploadInCollection = () => {
const button = document.getElementById("imageButton") as HTMLElement;
@@ -757,12 +682,6 @@ export class MobileInterface extends React.Component {
// Returns the image upload pop up
uploadImage = () => {
- if (this.imageUploadActive) {
- console.log("active");
- } else if (!this.imageUploadActive) {
-
- }
-
let doc;
let toggle;
if (this._homeMenu === false) {
@@ -777,6 +696,7 @@ export class MobileInterface extends React.Component {
);
}
+ // Radial menu can only be used if it is a colleciton and it is not a homeDoc
displayRadialMenu = () => {
if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc) {
return <RadialMenu />;
@@ -789,32 +709,19 @@ export class MobileInterface extends React.Component {
e.stopPropagation();
}
- uploadImageButton = () => {
- if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc && this._activeDoc._viewType !== "docking" && this._activeDoc.title !== "WORKSPACES") {
- return <div className="docButton"
- id="imageButton"
- title={Doc.isDocPinned(this._activeDoc) ? "Pen on" : "Pen off"}
- onClick={this.toggleUpload}>
- <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="upload"
- />
- </div>;
- }
- }
-
+ /**
+ * MENU BUTTON
+ * Switch view from mobile menu to access the mobile uploads
+ * Global function name: openMobileUploads()
+ */
switchToMobileUploads = () => {
- if (this._activeDoc.title !== "Presentation") {
- this._parents.push(this._activeDoc);
- }
const mobileUpload = Cast(Doc.UserDoc().rightSidebarCollection, Doc) as Doc;
- console.log(mobileUpload.title);
- this._activeDoc = mobileUpload;
- this.switchCurrentView((userDoc: Doc) => mobileUpload);
+ this.switchCurrentView(mobileUpload);
this._homeMenu = false;
}
render() {
- // trace();
- // TraceMobx();
+ trace();
return (
<div className="mobileInterface-container" onDragOver={this.onDragOver}>
<SettingsManager />
@@ -831,14 +738,12 @@ export class MobileInterface extends React.Component {
<div className="docButtonContainer">
{this.pinToPresentation()}
{this.downloadDocument()}
- {this.undo()}
- {this.drawInk()}
- {this.redo()}
- {/* {this.upload()} */}
+ {this.undo}
+ {this.drawInk}
+ {this.redo}
{this.uploadImageButton()}
- {/* {this.uploadAudioButton()} */}
</div>
- {this.displayWorkspaces()}
+ {this.displayWorkspaces}
{this.renderDefaultContent()}
</GestureOverlay>
{this.displayRadialMenu()}
@@ -848,15 +753,20 @@ export class MobileInterface extends React.Component {
}
-
-Scripting.addGlobal(function switchMobileView(doc: (userDoc: Doc) => Doc, renderView?: () => JSX.Element, onSwitch?: () => void) { return MobileInterface.Instance.switchCurrentView(doc, renderView, onSwitch); },
- "changes the active document displayed on the mobile, (doc: any)");
-Scripting.addGlobal(function openMobilePresentation() { return MobileInterface.Instance.setupDefaultPresentation(); },
- "opens the presentation on mobile");
-Scripting.addGlobal(function toggleMobileSidebar() { return MobileInterface.Instance.toggleSidebar(); });
-Scripting.addGlobal(function openMobileAudio() { return MobileInterface.Instance.toggleAudio(); });
-Scripting.addGlobal(function openMobileSettings() { return SettingsManager.Instance.open(); });
-Scripting.addGlobal(function openMobileWorkspaces() { return MobileInterface.Instance.openWorkspaces(); });
-Scripting.addGlobal(function uploadImageMobile() { return MobileInterface.Instance.toggleUpload(); });
-Scripting.addGlobal(function switchToMobileUploads() { return MobileInterface.Instance.switchToMobileUploads(); });
-Scripting.addGlobal(function switchToLibrary() { return MobileInterface.Instance.switchToLibrary(); }); \ No newline at end of file
+//Global functions for mobile menu
+Scripting.addGlobal(function switchToMobileLibrary() { return MobileInterface.Instance.switchToLibrary(); },
+ "opens the library to navigate through workspaces on Dash Mobile");
+Scripting.addGlobal(function openMobileUploads() { return MobileInterface.Instance.toggleUpload(); },
+ "opens the upload files menu for Dash Mobile");
+Scripting.addGlobal(function switchToMobileUploadCollection() { return MobileInterface.Instance.switchToMobileUploads(); },
+ "opens the mobile uploads collection on Dash Mobile");
+Scripting.addGlobal(function openMobileAudio() { return MobileInterface.Instance.toggleAudio(); },
+ "opens the record and dictate menu on Dash Mobile");
+Scripting.addGlobal(function switchToMobilePresentation() { return MobileInterface.Instance.setupDefaultPresentation(); },
+ "opens the presentation on Dash Mobile");
+Scripting.addGlobal(function openMobileSettings() { return SettingsManager.Instance.open(); },
+ "opens settings on Dash Mobile");
+
+// Other global functions for mobile
+Scripting.addGlobal(function switchMobileView(doc: Doc, renderView?: () => JSX.Element, onSwitch?: () => void) { return MobileInterface.Instance.switchCurrentView(doc, renderView, onSwitch); },
+ "changes the active document displayed on the Dash Mobile", "(doc: any)");
diff --git a/src/mobile/MobileMenu.scss b/src/mobile/MobileMenu.scss
index 254afa6d1..e69de29bb 100644
--- a/src/mobile/MobileMenu.scss
+++ b/src/mobile/MobileMenu.scss
@@ -1,475 +0,0 @@
-$navbar-height: 120px;
-$pathbar-height: 50px;
-
-* {
- margin: 0px;
- padding: 0px;
- box-sizing: border-box;
- font-family: "Open Sans";
-}
-
-body {
- overflow: hidden;
-}
-
-.navbar {
- position: fixed;
- top: 0px;
- left: 0px;
- width: 100vw;
- height: $navbar-height;
- background-color: whitesmoke;
- z-index: 150;
-}
-
-.navbar .cover {
- position: absolute;
- right: 0px;
- top: 0px;
- height: 120px;
- width: 120px;
- background-color: whitesmoke;
- z-index: 200;
-}
-
-.navbar .toggle-btn {
- position: absolute;
- right: 20px;
- top: 30px;
- height: 70px;
- width: 70px;
- transition: all 400ms ease-in-out 200ms;
- z-index: 180;
-}
-
-.navbar .background {
- position: absolute;
- right: 0px;
- top: 0px;
- height: 120px;
- width: 120px;
- //border: 1px solid black;
-}
-
-.navbar .background.active {
- background-color: lightgrey;
-}
-
-.navbar .toggle-btn-home {
- right: -200px;
-}
-
-.navbar .header {
- position: absolute;
- top: 50%;
- top: calc(9px + 50%);
- right: 50%;
- transform: translate(50%, -50%);
- font-size: 40;
- font-weight: 700;
- text-align: center;
- user-select: none;
- text-transform: uppercase;
- font-family: Arial, Helvetica, sans-serif;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- direction: ltr;
- width: 600px;
-}
-
-.navbar .toggle-btn span {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- width: 70%;
- height: 4px;
- background: black;
- transition: all 200ms ease;
- z-index: 180;
-}
-
-.navbar .toggle-btn span:nth-child(1) {
- transition: top 200ms ease-in-out;
- top: 30%;
-}
-
-.navbar .toggle-btn span:nth-child(3) {
- transition: top 200ms ease-in-out;
- top: 70%;
-}
-
-.navbar .toggle-btn.active {
- transition: transform 200ms ease-in-out 200ms;
- transform: rotate(135deg);
-}
-
-.navbar .toggle-btn.active span:nth-child(1) {
- top: 50%;
-}
-
-.navbar .toggle-btn.active span:nth-child(2) {
- transform: translate(-50%, -50%) rotate(90deg);
-}
-
-.navbar .toggle-btn.active span:nth-child(3) {
- top: 50%;
-}
-
-.sidebar {
- position: fixed;
- top: 120px;
- opacity: 0;
- right: -100%;
- width: 80%;
- height: calc(80% - (120px));
- z-index: 101;
- background-color: whitesmoke;
- transition: all 400ms ease 50ms;
- padding: 20px;
- // overflow-y: auto;
- // -webkit-overflow-scrolling: touch;
- // border-right: 5px solid black;
- box-shadow: 0 0 5px 5px grey;
-}
-
-.sidebar .item {
- width: 100%;
- padding: 13px 12px;
- border-bottom: 1px solid rgba(200, 200, 200, 0.7);
- font-family: Arial, Helvetica, sans-serif;
- font-style: normal;
- font-weight: normal;
- user-select: none;
- display: inline-flex;
- font-size: 35px;
- text-transform: uppercase;
- color: black;
-
-}
-
-.sidebar .ink:focus {
- outline: 1px solid blue;
-}
-
-.sidebarButtons {
- top: 80px;
- position: relative;
-}
-
-.blanket {
- position: fixed;
- top: 120px;
- opacity: 0.5;
- right: -100%;
- width: 100%;
- height: calc(100% - (120px));
- z-index: 101;
- background-color: grey;
- padding: 20px;
-}
-
-.blanket.active {
- position: absolute;
- right: 0%;
- z-index: 100;
-}
-
-.home {
- position: absolute;
- top: 30px;
- left: 30px;
- font-size: 60;
- user-select: none;
- text-transform: uppercase;
- font-family: Arial, Helvetica, sans-serif;
- z-index: 200;
-}
-
-.item-type {
- display: inline;
- text-transform: lowercase;
- margin-left: 20px;
- font-size: 35px;
- font-style: italic;
- color: rgb(28, 28, 28);
-}
-
-.item-title {
- max-width: 70%;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-
-.right {
- margin-left: 20px;
- z-index: 200;
-}
-
-.open {
- right: 20px;
- font-size: 35;
- position: absolute;
-}
-
-.left {
- width: 100%;
- height: 100%;
-}
-
-.sidebar .logout {
- width: 100%;
- padding: 13px 12px;
- border-bottom: 1px solid rgba(200, 200, 200, 0.7);
- font-family: Arial, Helvetica, sans-serif;
- font-style: normal;
- font-weight: normal;
- user-select: none;
- font-size: 30px;
- text-transform: uppercase;
- color: black;
-}
-
-.sidebar .settings {
- width: 100%;
- padding: 13px 12px;
- border-bottom: 1px solid rgba(200, 200, 200, 0.7);
- font-family: Arial, Helvetica, sans-serif;
- font-style: normal;
- font-weight: normal;
- user-select: none;
- font-size: 30px;
- text-transform: uppercase;
- color: black;
-}
-
-
-.sidebar.active {
- position: absolute;
- right:0%;
- opacity: 0.8;
- z-index: 101;
-}
-
-.back {
- position: absolute;
- left: 42px;
- top: 0;
- background: #1a1a1a;
- width: 50px;
- height: 100%;
- display: flex;
- justify-content: center;
- text-align: center;
- flex-direction: column;
- align-items: center;
- border-radius: 10px;
- font-size: 25px;
- user-select: none;
- z-index: 100;
-}
-
-.pathbar {
- position: fixed;
- top: 118px;
- left: 0px;
- background: #1a1a1a;
- z-index: 120;
- border-radius: 0px;
- width: 100%;
- height: 80px;
- overflow: hidden;
-}
-
-.pathname {
- position: relative;
- font-size: 25;
- top: 50%;
- width: 86%;
- left: 12%;
- color: whitesmoke;
- transform: translate(0%, -50%);
- z-index: 20;
- font-family: sans-serif;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- direction: rtl;
- text-align: left;
- text-transform: uppercase;
-}
-
-.docButton {
- position: relative;
- width: 100px;
- display: flex;
- height: 100px;
- font-size: 70px;
- text-align: center;
- border: 3px solid black;
- margin: 20px;
- z-index: 100;
- border-radius: 100%;
- justify-content: center;
- flex-direction: column;
- align-items: center;
-}
-
-.docButtonContainer {
- top: 80%;
- position: absolute;
- display: flex;
- transform: translate(-50%, 0);
- left: 50%;
- z-index: 100;
-}
-
-.scrollmenu {
- overflow: auto;
- width: 100%;
- height: 100%;
- white-space: nowrap;
- display: inline-flex;
-}
-
-.pathbarItem {
- position: relative;
- display: flex;
- align-items: center;
- color: whitesmoke;
- text-align: center;
- justify-content: center;
- user-select: none;
- transform: translate(100px, 0px);
- font-size: 30px;
- padding: 10px;
- text-transform: uppercase;
-}
-
-.pathbarText {
- font-family: sans-serif;
- text-align: center;
- height: 50px;
- padding: 10px;
- font-size: 30px;
- border-radius: 10px;
- text-transform: uppercase;
- margin-left: 20px;
- position: relative;
-}
-
-
-.pathIcon {
- transform: translate(0px, 0px);
- position: relative;
-}
-
-.hidePath {
- position: absolute;
- height: 100%;
- width: 200px;
- left: 0px;
- top: 0px;
- background-image: linear-gradient(to right, #1a1a1a, rgba(0, 0, 0, 0));
- text-align: center;
- user-select: none;
- z-index: 99;
- pointer-events: none;
-}
-
-.toolbar {
- left: 50%;
- transform: translate(-50%);
- position: absolute;
- height: max-content;
- top: 0px;
- border-radius: 20px;
- background-color: lightgrey;
- opacity: 0;
- transition: all 400ms ease 50ms;
-}
-
-.toolbar.active {
- display: inline-block;
- width: 300px;
- padding: 5px;
- opacity: 1;
- height: max-content;
- top: -450px;
-}
-
-.colorSelector {
- position: absolute;
- top: 550px;
- left: 300px;
- transform: translate(-50%, 0);
- z-index: 100;
- display: inline-flex;
- width: max-content;
- height: max-content;
- pointer-events: all;
- font-size: 90px;
-}
-
-.widthSelector {
- display: inline-flex;
- width: max-content;
- height: 100px;
- padding: 10px;
-}
-
-.slider {
- -webkit-appearance: none;
- /* Override default CSS styles */
- appearance: none;
- width: 100%;
- /* Full-width */
- height: 25px;
- /* Specified height */
- background: #d3d3d3;
- /* Grey background */
- outline: none;
- /* Remove outline */
-}
-
-.colorButton {
- width: 70px;
- margin: 10px;
- height: 70px;
- border-style: solid;
- border-width: 3px;
- border-radius: 100%;
-}
-
-.homeSwitch {
- position: fixed;
- top: 212;
- right: 36px;
- display: inline-flex;
- width: max-content;
- z-index: 99;
- height: 70px;
-}
-
-.list {
- width: 70px;
- height: 70px;
- margin: 5;
- padding: 10;
- align-items: center;
- text-align: center;
- font-size: 50;
- border-style: solid;
- border-width: 3;
- border-color: black;
- background: whitesmoke;
- align-self: center;
- border-radius: 10px;
-}
-
-.list.active {
- color: darkred;
- border-color: darkred;
-} \ No newline at end of file