aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgeireann <60007097+geireann@users.noreply.github.com>2020-06-19 14:14:28 +0800
committergeireann <60007097+geireann@users.noreply.github.com>2020-06-19 14:14:28 +0800
commit10754a14c8d0dda68f2484e523f6901b3e7daee3 (patch)
tree7e7495746624949a3b9f7da85f3967af9e9e6b9e
parentcb5fa90bb580c2d618e279275c1e2cb49ce3d90c (diff)
css changes and bug fixes
Presentation Undo / Redo Image upload Record Audio
-rw-r--r--src/client/views/collections/CollectionView.tsx2
-rw-r--r--src/client/views/collections/CollectionViewChromes.scss6
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx2
-rw-r--r--src/client/views/nodes/AudioBox.tsx2
-rw-r--r--src/client/views/nodes/PresBox.scss10
-rw-r--r--src/mobile/AudioUpload.scss119
-rw-r--r--src/mobile/AudioUpload.tsx237
-rw-r--r--src/mobile/ImageUpload.scss15
-rw-r--r--src/mobile/ImageUpload.tsx58
-rw-r--r--src/mobile/MobileInterface.tsx205
-rw-r--r--src/mobile/MobileMenu.scss15
11 files changed, 531 insertions, 140 deletions
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index a700d0dfb..7c5c87e3e 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -283,7 +283,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
!existingOnClick && ContextMenu.Instance?.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" });
if (!Doc.UserDoc().noviceMode) {
- const more = ContextMenu.Instance.findByDescription("More...");
+ const more = ContextMenu.Instance?.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" });
diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss
index f85cbfee2..54ee4ab3b 100644
--- a/src/client/views/collections/CollectionViewChromes.scss
+++ b/src/client/views/collections/CollectionViewChromes.scss
@@ -80,6 +80,12 @@
// margin-top: 10px;
}
+ @media only screen and (max-width: 1000) {
+ .collectionViewBaseChrome-collapse {
+ display: none;
+ }
+ }
+
.collectionViewBaseChrome-template,
.collectionViewBaseChrome-viewModes {
display: grid;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 82d6dee73..327e172bb 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1199,7 +1199,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
onContextMenu = (e: React.MouseEvent) => {
if (this.props.annotationsKey) return;
- ContextMenu.Instance.addItem({
+ ContextMenu.Instance?.addItem({
description: (this._timelineVisible ? "Close" : "Open") + " Animation Timeline", event: action(() => {
this._timelineVisible = !this._timelineVisible;
}), icon: this._timelineVisible ? faEyeSlash : faEye
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 2e0be1c6a..cb0582d87 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -161,7 +161,7 @@ export class AudioBox extends ViewBoxBaseComponent<FieldViewProps, AudioDocument
const funcs: ContextMenuProps[] = [];
funcs.push({ description: (this.layoutDoc.playOnSelect ? "Don't play" : "Play") + " when document selected", event: () => this.layoutDoc.playOnSelect = !this.layoutDoc.playOnSelect, icon: "expand-arrows-alt" });
- ContextMenu.Instance.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" });
+ ContextMenu.Instance?.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" });
}
stopRecording = action(() => {
diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss
index ccce6e627..e62aa48fb 100644
--- a/src/client/views/nodes/PresBox.scss
+++ b/src/client/views/nodes/PresBox.scss
@@ -105,15 +105,13 @@
}
.presBox-cont .presBox-buttons .presBox-button {
- margin-right: 10px;
- margin-left: 10px;
+ margin-top: 5%;
height: 250;
- width: 250;
- font-size: 70;
- border-radius: 25px;
+ width: 300;
+ font-size: 100;
display: flex;
align-items: center;
- background: #323232;
+ background: 323232;
color: white;
}
diff --git a/src/mobile/AudioUpload.scss b/src/mobile/AudioUpload.scss
new file mode 100644
index 000000000..5f0ba465a
--- /dev/null
+++ b/src/mobile/AudioUpload.scss
@@ -0,0 +1,119 @@
+@import "../client/views/globalCssVariables.scss";
+
+.audioUpload_cont {
+ display: flex;
+ justify-content: center;
+ flex-direction: column;
+ align-items: center;
+ max-width: 400px;
+ min-width: 400px;
+
+ .upload_label {
+ font-size: 3em;
+ font-weight: 700;
+ color: white;
+ background-color: black;
+ display: inline-block;
+ margin: 10;
+ width: 100%;
+ border-radius: 10px;
+ }
+
+ .file {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ direction: ltr;
+ }
+
+ .upload_label:hover {
+ background-color: darkred;
+ }
+
+ .button_file {
+ text-align: center;
+ height: 50%;
+ width: 50%;
+ background-color: paleturquoise;
+ color: grey;
+ font-size: 3em;
+ }
+
+ .inputfile {
+ width: 0.1px;
+ height: 0.1px;
+ opacity: 0;
+ overflow: hidden;
+ position: absolute;
+ z-index: -1;
+ }
+
+ .inputfile+label {
+ font-size: 3em;
+ font-weight: 700;
+ color: white;
+ background-color: black;
+ display: inline-block;
+ margin: 10px;
+ width: 100%;
+ border-radius: 10px;
+ }
+
+ .inputfile:focus+label,
+ .inputfile+label:hover {
+ background-color: darkred;
+ }
+
+ .status {
+ font-size: 2em;
+ }
+
+}
+
+.backgroundUpload {
+ height: 100vh;
+ top: 0;
+ z-index: 999;
+ width: 100vw;
+ position: absolute;
+ background-color: lightgrey;
+ opacity: 0.4;
+}
+
+.audio-upload {
+ top: 100%;
+ opacity: 0;
+}
+
+.audio-upload.active {
+ top: 0;
+ position: absolute;
+ z-index: 999;
+ height: 100vh;
+ width: 100vw;
+ opacity: 1;
+}
+
+.uploadContainer {
+ top: 40;
+ position: absolute;
+ z-index: 1000;
+ height: 20vh;
+ width: 80vw;
+ opacity: 1;
+}
+
+.loadingImage {
+ display: inline-flex;
+ width: max-content;
+}
+
+.loadingSlab {
+ position: relative;
+ width: 30px;
+ height: 30px;
+ margin: 10;
+ border-radius: 20px;
+ opacity: 0.3;
+ background-color: black;
+} \ No newline at end of file
diff --git a/src/mobile/AudioUpload.tsx b/src/mobile/AudioUpload.tsx
new file mode 100644
index 000000000..7ea11ee84
--- /dev/null
+++ b/src/mobile/AudioUpload.tsx
@@ -0,0 +1,237 @@
+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 } from 'mobx';
+import { Utils, emptyPath, returnFalse, emptyFunction, returnOne, returnZero, returnTrue } from '../Utils';
+import { Networking } from '../client/Network';
+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 { 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>();
+
+@observer
+export class AudioUpload extends React.Component {
+ @observable error: string = "";
+ @observable status: string = "";
+ @observable nm: string = "Choose files";
+ @observable process: string = "";
+
+ onClick = async () => {
+ try {
+ await Docs.Prototypes.initialize();
+ const imgPrev = document.getElementById("img_preview");
+ const slab1 = document.getElementById("slab1");
+ if (slab1) {
+ slab1.style.opacity = "1";
+ }
+ if (imgPrev) {
+ const files: FileList | null = inputRef.current!.files;
+ const slab2 = document.getElementById("slab2");
+ if (slab2) {
+ slab2.style.opacity = "1";
+ }
+ 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);
+ const slab3 = document.getElementById("slab3");
+ if (slab3) {
+ slab3.style.opacity = "1";
+ }
+ res.map(async ({ result }) => {
+ const name = file.name;
+ if (result instanceof Error) {
+ return;
+ }
+ 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 });
+ }
+ const slab4 = document.getElementById("slab4");
+ if (slab4) {
+ slab4.style.opacity = "1";
+ }
+ const res = await rp.get(Utils.prepend("/getUserDocumentId"));
+ if (!res) {
+ throw new Error("No user id returned");
+ }
+ const field = await DocServer.GetRefField(res);
+ let pending: Opt<Doc>;
+ if (field instanceof Doc) {
+ pending = await Cast(field.mobileUpload, 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";
+ const slab5 = document.getElementById("slab5");
+ if (slab5) {
+ slab5.style.opacity = "1";
+ }
+ this.process = "File " + (index + 1).toString() + " Uploaded";
+ const slab6 = document.getElementById("slab6");
+ if (slab6) {
+ slab6.style.opacity = "1";
+ }
+ const slab7 = document.getElementById("slab7");
+ if (slab7) {
+ slab7.style.opacity = "1";
+ }
+
+ }
+ });
+ }
+ } else {
+ this.process = "No file selected";
+ }
+ setTimeout(this.clearUpload, 3000);
+ }
+ } catch (error) {
+ this.error = JSON.stringify(error);
+ }
+ }
+
+ // Updates label after a files is selected (so user knows a file is uploaded)
+ inputLabel = async () => {
+ 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";
+ }
+ }
+
+ @action
+ clearUpload = () => {
+ const slab1 = document.getElementById("slab1");
+ if (slab1) {
+ slab1.style.opacity = "0.4";
+ }
+ const slab2 = document.getElementById("slab2");
+ if (slab2) {
+ slab2.style.opacity = "0.4";
+ }
+ const slab3 = document.getElementById("slab3");
+ if (slab3) {
+ slab3.style.opacity = "0.4";
+ }
+ const slab4 = document.getElementById("slab4");
+ if (slab4) {
+ slab4.style.opacity = "0.4";
+ }
+ const slab5 = document.getElementById("slab5");
+ if (slab5) {
+ slab5.style.opacity = "0.4";
+ }
+ const slab6 = document.getElementById("slab6");
+ if (slab6) {
+ slab6.style.opacity = "0.4";
+ }
+ const slab7 = document.getElementById("slab7");
+ if (slab7) {
+ slab7.style.
+ opacity = "0.4";
+ }
+ this.nm = "Choose files";
+
+ if (inputRef.current) {
+ inputRef.current.value = "";
+ }
+ this.process = "";
+ console.log(inputRef.current!.files);
+ }
+
+
+
+ private get uploadInterface() {
+ const audioDoc = Cast(Docs.Create.AudioDocument(nullAudio, { title: "mobile audio" }), Doc) as Doc;
+
+ return (
+ <div className="imgupload_cont">
+ <div className="closeUpload" onClick={MobileInterface.Instance.toggleAudio}>
+ <FontAwesomeIcon icon="window-close" size={"lg"} />
+ </div>
+ <DocumentView
+ Document={audioDoc}
+ DataDoc={undefined}
+ LibraryPath={emptyPath}
+ addDocument={returnFalse}
+ addDocTab={returnFalse}
+ pinToPres={emptyFunction}
+ rootSelected={returnFalse}
+ removeDocument={undefined}
+ onClick={undefined}
+ ScreenToLocalTransform={Transform.Identity}
+ ContentScaling={returnOne}
+ PanelWidth={() => 1000}
+ PanelHeight={() => 1000}
+ NativeHeight={returnZero}
+ NativeWidth={returnZero}
+ renderDepth={0}
+ focus={emptyFunction}
+ backgroundColor={() => "white"}
+ parentActive={returnTrue}
+ whenActiveChanged={emptyFunction}
+ bringToFront={emptyFunction}
+ ContainingCollectionView={undefined}
+ ContainingCollectionDoc={undefined}
+ />
+ </div>
+ );
+ }
+
+ @observable private dialogueBoxOpacity = 1;
+ @observable private overlayOpacity = 0.4;
+
+ render() {
+ return (
+ <MainViewModal
+ contents={this.uploadInterface}
+ isDisplayed={true}
+ interactive={true}
+ dialogueBoxDisplayedOpacity={this.dialogueBoxOpacity}
+ overlayDisplayedOpacity={this.overlayOpacity}
+ />
+ );
+ }
+
+}
+
+
diff --git a/src/mobile/ImageUpload.scss b/src/mobile/ImageUpload.scss
index 95c0c2680..b64aac338 100644
--- a/src/mobile/ImageUpload.scss
+++ b/src/mobile/ImageUpload.scss
@@ -55,6 +55,7 @@
background-color: black;
display: inline-block;
margin: 10px;
+ margin-top: 30px;
width: 100%;
border-radius: 10px;
}
@@ -106,16 +107,15 @@
.closeUpload {
position: absolute;
border-radius: 10px;
- top: 39.7%;
- color: grey;
- font-size: 40;
- left: 65.8%;
+ top: 3;
+ color: black;
+ font-size: 30;
+ right: 3;
z-index: 1002;
padding: 0px 3px;
- background: aliceblue;
+ background: rgba(0, 0, 0, 0);
transition: 0.5s ease all;
- border: 3px solid;
- border-color: black;
+ border: 0px solid;
}
.loadingImage {
@@ -131,4 +131,5 @@
border-radius: 20px;
opacity: 0.3;
background-color: black;
+ transition: all 2s, opacity 1.5s;
} \ No newline at end of file
diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx
index b66f0461d..744a45507 100644
--- a/src/mobile/ImageUpload.tsx
+++ b/src/mobile/ImageUpload.tsx
@@ -15,6 +15,8 @@ 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;
@@ -29,7 +31,7 @@ export interface ImageUploadProps {
const inputRef = React.createRef<HTMLInputElement>();
@observer
-export class Uploader extends React.Component {
+export class Uploader extends React.Component<ImageUploadProps> {
@observable error: string = "";
@observable status: string = "";
@observable nm: string = "Choose files";
@@ -39,25 +41,22 @@ export class Uploader extends React.Component {
try {
await Docs.Prototypes.initialize();
const imgPrev = document.getElementById("img_preview");
+ // Slab 1
const slab1 = document.getElementById("slab1");
- if (slab1) {
- slab1.style.opacity = "1";
- }
+ if (slab1) slab1.style.opacity = "1";
if (imgPrev) {
const files: FileList | null = inputRef.current!.files;
+ // Slab 2
const slab2 = document.getElementById("slab2");
- if (slab2) {
- slab2.style.opacity = "1";
- }
+ if (slab2) slab2.style.opacity = "1";
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
const slab3 = document.getElementById("slab3");
- if (slab3) {
- slab3.style.opacity = "1";
- }
+ if (slab3) slab3.style.opacity = "1";
res.map(async ({ result }) => {
const name = file.name;
if (result instanceof Error) {
@@ -67,16 +66,15 @@ export class Uploader extends React.Component {
let doc = null;
console.log("type: " + file.type);
if (file.type === "video/mp4") {
- doc = Docs.Create.VideoDocument(path, { _nativeWidth: 200, _width: 200, title: name });
+ doc = Docs.Create.VideoDocument(path, { _nativeWidth: 400, _width: 400, title: name });
} else if (file.type === "application/pdf") {
- doc = Docs.Create.PdfDocument(path, { _width: 200, title: name });
+ doc = Docs.Create.PdfDocument(path, { _nativeWidth: 400, _width: 400, title: name });
} else {
- doc = Docs.Create.ImageDocument(path, { _nativeWidth: 200, _width: 200, title: name });
+ doc = Docs.Create.ImageDocument(path, { _nativeWidth: 400, _width: 400, title: name });
}
+ // Slab 4
const slab4 = document.getElementById("slab4");
- if (slab4) {
- slab4.style.opacity = "1";
- }
+ if (slab4) slab4.style.opacity = "1";
const res = await rp.get(Utils.prepend("/getUserDocumentId"));
if (!res) {
throw new Error("No user id returned");
@@ -84,30 +82,23 @@ export class Uploader extends React.Component {
const field = await DocServer.GetRefField(res);
let pending: Opt<Doc>;
if (field instanceof Doc) {
- pending = await Cast(field.rightSidebarCollection, Doc);
+ const parent = await Cast(this.props.Document.data, listSpec(Doc));
+ const u = CurrentUserUtils.setupMobileUpload(this.props.Document);
+ if (parent && !parent.includes(u)) parent.push(u);
+ pending = await Cast(u, Doc);
}
if (pending) {
const data = await Cast(pending.data, listSpec(Doc));
- if (data) {
- data.push(doc);
- } else {
- pending.data = new List([doc]);
- }
+ if (data) data.push(doc);
+ else pending.data = new List([doc]);
this.status = "finished";
const slab5 = document.getElementById("slab5");
- if (slab5) {
- slab5.style.opacity = "1";
- }
+ if (slab5) slab5.style.opacity = "1";
this.process = "File " + (index + 1).toString() + " Uploaded";
const slab6 = document.getElementById("slab6");
- if (slab6) {
- slab6.style.opacity = "1";
- }
+ if (slab6) slab6.style.opacity = "1";
const slab7 = document.getElementById("slab7");
- if (slab7) {
- slab7.style.opacity = "1";
- }
-
+ if (slab7) slab7.style.opacity = "1";
}
});
}
@@ -178,6 +169,9 @@ export class Uploader extends React.Component {
private get uploadInterface() {
return (
<div className="imgupload_cont">
+ <div className="closeUpload" onClick={MobileInterface.Instance.toggleUpload}>
+ <FontAwesomeIcon icon="window-close" size={"lg"} />
+ </div>
<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}>
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index 4000bee85..612b112e6 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, faExternalLinkSquareAlt, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus,
+ faTasks, faFolderOpen, faAngleDoubleLeft, 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,
@@ -25,6 +25,7 @@ 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";
@@ -39,8 +40,9 @@ import { RadialMenu } from "../client/views/nodes/RadialMenu";
import { UndoManager } from "../client/util/UndoManager";
import { MainView } from "../client/views/MainView";
import { List } from "../fields/List";
+import { AudioUpload } from "./AudioUpload";
-library.add(faTasks, faExternalLinkSquareAlt, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus,
+library.add(faTasks, 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,
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,
@@ -54,17 +56,18 @@ export class MobileInterface extends React.Component {
@computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeMobile, Doc)) : CurrentUserUtils.GuestMobile; }
@observable private mainDoc: any = CurrentUserUtils.setupActiveMobileMenu(this.userDoc);
@observable private renderView?: () => JSX.Element;
- @observable private sidebarActive: boolean = false;
- @observable private imageUploadActive: boolean = false;
- @observable private menuListView: boolean = false;
- @observable private _ink: boolean = false;
-
- public _activeDoc: Doc = this.mainDoc;
- public _homeDoc: Doc = this.mainDoc;
- private _homeMenu: boolean = true;
- private _child: Doc | null = null;
- private _parents: Array<Doc> = [];
- private _library: Doc = CurrentUserUtils.setupLibrary(this.userDoc);
+ @observable private sidebarActive: boolean = false; //to toggle sidebar display
+ @observable private imageUploadActive: boolean = false; //to toggle image upload
+ @observable private audioUploadActive: boolean = false;
+ @observable private menuListView: boolean = false; //to switch between menu view (list / icon)
+ @observable private _ink: boolean = false; //toggle whether ink is being dispalyed
+
+ public _activeDoc: Doc = this.mainDoc; // doc updated as the active mobile page is updated (initially home menu)
+ public _homeDoc: Doc = this.mainDoc; // home menu as a document
+ private _homeMenu: boolean = true; // to determine whether currently at home menu
+ private _child: Doc | null = null; // currently selected document
+ private _parents: Array<Doc> = []; // array of parent docs (for pathbar)
+ private _library: Doc = CurrentUserUtils.setupLibrary(this.userDoc); // to access documents in Dash Web
constructor(props: Readonly<{}>) {
super(props);
@@ -119,7 +122,7 @@ export class MobileInterface extends React.Component {
}
/**
- * Back method for navigating
+ * Back method for navigating through items
*/
back = () => {
const header = document.getElementById("header") as HTMLElement;
@@ -182,7 +185,7 @@ export class MobileInterface extends React.Component {
if (this.mainContainer) {
const backgroundColor = () => "white";
return (
- <div style={{ position: "relative", top: '200px', height: `calc(100% - 350px)`, width: "100%", left: "0%" }}>
+ <div style={{ position: "relative", top: '198px', height: `calc(100% - 350px)`, width: "100%", left: "0%" }}>
<DocumentView
Document={this.mainContainer}
DataDoc={undefined}
@@ -213,6 +216,11 @@ export class MobileInterface extends React.Component {
}
}
+ /**
+ * Note: window.innerWidth and window.screen.width compute different values.
+ * window.screen.width is the display size, however window.innerWidth is the
+ * display resolution which computes differently.
+ */
returnWidth = () => window.innerWidth; //The windows width
returnHeight = () => (window.innerHeight - 300); //Calculating the windows height (-300 to account for topbar)
@@ -224,11 +232,7 @@ export class MobileInterface extends React.Component {
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._homeMenu = false;
- this.toggleSidebar();
+ this.openFromSidebar(doc);
} else if (doc.type === "collection" && children.length === 0) console.log("This collection has no children");
else {
this._parents.push(this._activeDoc);
@@ -239,6 +243,14 @@ export class MobileInterface extends React.Component {
}
}
+ openFromSidebar = (doc: Doc) => {
+ this._parents.push(this._activeDoc);
+ this._activeDoc = doc;
+ this.switchCurrentView((userDoc: Doc) => doc);
+ this._homeMenu = false;
+ this.toggleSidebar();
+ }
+
/**
* Handles creation of array which is then rendered in renderPathbar()
*/
@@ -350,14 +362,6 @@ export class MobileInterface extends React.Component {
</div>
</div>
{this.renderPathbar()}
- <div className="sidebar" id="sidebar">
- <div className="sidebarButtons">
- <div
- className="item"
- onClick={() => MainView.Instance?.createNewWorkspace()}>Create New Workspace
- </div>
- </div>
- </div>
</div>
);
}
@@ -377,6 +381,7 @@ export class MobileInterface extends React.Component {
<div className="item-title"> {doc.title} </div>
<div className="item-type">{doc.type}</div>
<FontAwesomeIcon className="right" icon="angle-right" size="lg" />
+ <FontAwesomeIcon className="open" onClick={() => this.openFromSidebar(doc)} icon="external-link-alt" size="lg" />
</div>);
}
});
@@ -398,9 +403,13 @@ export class MobileInterface extends React.Component {
{this._child ?
<>
{buttons}
- <div className="item" key="home" onClick={this.returnMain}>
- Return to library
- </div>
+ <div
+ className="item" key="home"
+ onClick={this.returnMain}
+ style={{ opacity: 0.7 }}>
+ <FontAwesomeIcon className="right" icon="angle-double-left" size="lg" />
+ <div className="item-type">Return to library</div>
+ </div>
</> :
<>
{buttons}
@@ -455,7 +464,7 @@ export class MobileInterface extends React.Component {
return <div className="docButton"
title={Doc.isDocPinned(this._activeDoc) ? "Pen on" : "Pen off"}
style={{ backgroundColor: "black", color: "white" }}
- onClick={this.uploadAudio}
+ // onClick={this.uploadAudio}
>
<FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="upload"
/>
@@ -492,21 +501,45 @@ export class MobileInterface extends React.Component {
}
}
+ undo = () => {
+ if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc) {
+ return (<>
+ <div className="docButton"
+ style={{ backgroundColor: "black", color: "white" }}
+ id="undoButton"
+ title="undo"
+ onClick={(e: React.MouseEvent) => {
+ UndoManager.Undo();
+ e.stopPropagation();
+ }}>
+ <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="undo-alt" />
+ </div>
+ </>);
+ }
+ }
+
+ redo = () => {
+ if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc) {
+ return (<>
+ <div className="docButton"
+ style={{ backgroundColor: "black", color: "white" }}
+ id="undoButton"
+ title="redo"
+ onClick={(e: React.MouseEvent) => {
+ UndoManager.Redo();
+ e.stopPropagation();
+ }}>
+ <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="redo-alt" />
+ </div>
+ </>);
+ }
+ }
+
// Button for switching into ink mode
drawInk = () => {
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"}
@@ -514,23 +547,29 @@ 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"
+ </>);
+ }
+ }
+
+ // 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> */}
+ </div>
</>);
}
}
// Button to download images on the mobile
downloadDocument = () => {
- if (this._activeDoc.type === "image") {
+ if (this._activeDoc.type === "image" || this._activeDoc.type === "pdf" || this._activeDoc.type === "video") {
const url = this._activeDoc["data-path"]?.toString();
return <div className="docButton"
title={"Download Image"}
@@ -559,24 +598,21 @@ export class MobileInterface extends React.Component {
}
}
- // 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);
- }
- }
+ // // 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));
- panelHeight = () => window.innerHeight;
- panelWidth = () => window.innerWidth;
+ // if (data) {
+ // data.push(audioDoc);
+ // }
+ // }
// Button for pinning images to presentation
pinToPresentation = () => {
// Only making button available if it is an image
- if (this._activeDoc.type === "image") {
+ if (!(this._activeDoc.type === "collection" || this._activeDoc.type === "presentation")) {
const isPinned = this._activeDoc && Doc.isDocPinned(this._activeDoc);
return <div className="docButton"
title={Doc.isDocPinned(this._activeDoc) ? "Unpin from presentation" : "Pin to presentation"}
@@ -611,7 +647,7 @@ export class MobileInterface extends React.Component {
}
}
- // Logics for switching the menu into the icons
+ // Logic for switching the menu into the icons
@action
changeToIconView = () => {
if (this._homeDoc._viewType = "stacking") {
@@ -635,7 +671,7 @@ export class MobileInterface extends React.Component {
}
}
- // Logics for switching the menu into the stacking view
+ // Logic for switching the menu into the stacking view
@action
changeToListView = () => {
if (this._homeDoc._viewType = "masonry") {
@@ -674,29 +710,16 @@ export class MobileInterface extends React.Component {
@action
toggleUpload = () => this.imageUploadActive = !this.imageUploadActive
+ // For toggling image upload pop up
+ @action
+ toggleAudio = () => this.audioUploadActive = !this.audioUploadActive
+
// For closing the image upload pop up
@action
closeUpload = () => {
this.imageUploadActive = false;
}
- // Returns the image upload pop up
- uploadImage = () => {
- if (this.imageUploadActive) {
- console.log("active");
- } else if (!this.imageUploadActive) {
-
- }
- return (
- <div>
- <div className="closeUpload" onClick={this.toggleUpload}>
- <FontAwesomeIcon icon="window-close" size={"lg"} />
- </div>
- <Uploader />
- </div>
- );
- }
-
displayRadialMenu = () => {
if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc) {
return <RadialMenu />;
@@ -713,7 +736,10 @@ export class MobileInterface extends React.Component {
<div className="mobileInterface-container" onDragOver={this.onDragOver}>
<SettingsManager />
<div className={`image-upload ${this.imageUploadActive ? "active" : ""}`}>
- {this.uploadImage()}
+ <Uploader Document={this._homeMenu ? this._library : this._activeDoc} />
+ </div>
+ <div className={`audio-upload ${this.audioUploadActive ? "active" : ""}`}>
+ <AudioUpload />
</div>
{this.switchMenuView()}
{this.inkMenu()}
@@ -721,8 +747,11 @@ export class MobileInterface extends React.Component {
<div className="docButtonContainer">
{this.pinToPresentation()}
{this.downloadDocument()}
- {this.drawInk()}
- {this.uploadAudioButton()}
+ {this.undo()}
+ {this.redo()}
+ {this.upload()}
+ {/* {this.drawInk()} */}
+ {/* {this.uploadAudioButton()} */}
</div>
{this.displayWorkspaces()}
{this.renderDefaultContent()}
@@ -738,7 +767,7 @@ 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); });
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 openMobileAudio() { return MobileInterface.Instance.toggleAudio(); });
Scripting.addGlobal(function openMobileSettings() { return SettingsManager.Instance.open(); });
Scripting.addGlobal(function switchToLibrary() { return MobileInterface.Instance.switchToLibrary(); });
Scripting.addGlobal(function uploadImageMobile() { return MobileInterface.Instance.toggleUpload(); });
diff --git a/src/mobile/MobileMenu.scss b/src/mobile/MobileMenu.scss
index 6304ff5e4..87731655a 100644
--- a/src/mobile/MobileMenu.scss
+++ b/src/mobile/MobileMenu.scss
@@ -175,6 +175,11 @@ body {
z-index: 200;
}
+.open {
+ right: 20px;
+ position: absolute;
+}
+
.left {
width: 100%;
height: 100%;
@@ -262,15 +267,17 @@ body {
.docButton {
position: relative;
width: 100px;
+ display: flex;
height: 100px;
font-size: 70px;
- padding: 5px;
text-align: center;
- border-style: solid;
- border-radius: 50px;
- border-width: 5px;
+ border: 3px solid black;
margin: 20px;
z-index: 100;
+ border-radius: 100%;
+ justify-content: center;
+ flex-direction: column;
+ align-items: center;
}
.docButtonContainer {