aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--deploy/mobile/image.html11
-rw-r--r--src/.DS_Storebin6148 -> 8196 bytes
-rw-r--r--src/client/util/CurrentUserUtils.ts4
-rw-r--r--src/client/views/nodes/FieldView.tsx6
-rw-r--r--src/mobile/ImageUpload.scss55
-rw-r--r--src/mobile/ImageUpload.tsx67
-rw-r--r--src/mobile/MobileInterface.scss9
-rw-r--r--src/mobile/MobileInterface.tsx600
-rw-r--r--src/mobile/MobileMenu.scss240
-rw-r--r--webpack.config.js2
10 files changed, 777 insertions, 217 deletions
diff --git a/deploy/mobile/image.html b/deploy/mobile/image.html
index 6424d2a60..cca6f763b 100644
--- a/deploy/mobile/image.html
+++ b/deploy/mobile/image.html
@@ -1,15 +1,16 @@
<html>
<head>
- <title>Test view</title>
+ <title>Dash Mobile</title>
<link href="https://fonts.googleapis.com/css?family=Fjalla+One|Hind+Siliguri:300" rel="stylesheet">
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
+ integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/typescript/3.3.1/typescript.min.js"></script>
</head>
<body>
- <div id="root">
- <p>Capture Image: <input type="file" accept="image/*" id="capture">
- </div>
- <script src="../imageUpload.js"></script>
+ <div id="root"></div>
+ <script src="../mobileInterface.js"></script>
</body>
</html> \ No newline at end of file
diff --git a/src/.DS_Store b/src/.DS_Store
index 5b35884bd..299b902c6 100644
--- a/src/.DS_Store
+++ b/src/.DS_Store
Binary files differ
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 496099557..377f908e9 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -444,6 +444,10 @@ export class CurrentUserUtils {
});
}
+ static setupMobileMenu(userDoc: Doc) {
+ return CurrentUserUtils.setupWorkspaces(userDoc);
+ }
+
static setupMobileInkingDoc(userDoc: Doc) {
return Docs.Create.FreeformDocument([], { title: "Mobile Inking", backgroundColor: "white" });
}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index e9dc43bd8..0bb1401aa 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -91,9 +91,9 @@ export class FieldView extends React.Component<FieldViewProps> {
else if (field instanceof VideoField) {
return <VideoBox {...this.props} />;
}
- else if (field instanceof AudioField) {
- return <AudioBox {...this.props} />;
- } else if (field instanceof DateField) {
+ // else if (field instanceof AudioField) {
+ // return <AudioBox {...this.props} />;
+ else if (field instanceof DateField) {
return <p>{field.date.toLocaleString()}</p>;
}
else if (field instanceof Doc) {
diff --git a/src/mobile/ImageUpload.scss b/src/mobile/ImageUpload.scss
index eea69b81c..715924cba 100644
--- a/src/mobile/ImageUpload.scss
+++ b/src/mobile/ImageUpload.scss
@@ -1,12 +1,26 @@
@import "../client/views/globalCssVariables.scss";
.imgupload_cont {
- display: flex;
- justify-content: center;
- flex-direction: column;
- align-items: center;
- width: 100vw;
- height: 100vh;
+ // display: flex;
+ // justify-content: center;
+ // flex-direction: column;
+ // align-items: center;
+ // width: 100vw;
+ // height: 100vh;
+
+ .upload_label {
+ font-weight: normal !important;
+ 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: 35px;
+ text-transform: uppercase;
+ color: black;
+ }
.button_file {
text-align: center;
@@ -21,14 +35,27 @@
display: none;
}
- .upload_label,
+ // .upload_label,
+ // .upload_button {
+ // background: $dark-color;
+ // font-size: 500%;
+ // font-family: $sans-serif;
+ // text-align: center;
+ // padding: 5vh;
+ // margin-bottom: 20px;
+ // color: white;
+ // }
+
.upload_button {
- background: $dark-color;
- font-size: 500%;
- font-family: $sans-serif;
- text-align: center;
- padding: 5vh;
- margin-bottom: 20px;
- color: white;
+ 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: 35px;
+ text-transform: uppercase;
+ color: black;
}
} \ No newline at end of file
diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx
index b15042f9f..2552e2112 100644
--- a/src/mobile/ImageUpload.tsx
+++ b/src/mobile/ImageUpload.tsx
@@ -4,16 +4,19 @@ import { Docs } from '../client/documents/Documents';
import "./ImageUpload.scss";
import React = require('react');
import { DocServer } from '../client/DocServer';
-import { Opt, Doc } from '../fields/Doc';
+import { Opt, Doc, DocListCast } from '../fields/Doc';
import { Cast } from '../fields/Types';
import { listSpec } from '../fields/Schema';
import { List } from '../fields/List';
import { observer } from 'mobx-react';
import { observable } from 'mobx';
import { Utils } from '../Utils';
-import MobileInterface from './MobileInterface';
-import { CurrentUserUtils } from '../client/util/CurrentUserUtils';
-import { resolvedPorts } from '../client/views/Main';
+import { Networking } from '../client/Network';
+import { MobileDocumentUploadContent } from '../server/Message';
+
+export interface ImageUploadProps {
+ Document: Doc;
+}
// const onPointerDown = (e: React.TouchEvent) => {
// let imgInput = document.getElementById("input_image_file");
@@ -24,7 +27,7 @@ import { resolvedPorts } from '../client/views/Main';
const inputRef = React.createRef<HTMLInputElement>();
@observer
-class Uploader extends React.Component {
+export class Uploader extends React.Component<ImageUploadProps> {
@observable error: string = "";
@observable status: string = "";
@@ -39,20 +42,15 @@ class Uploader extends React.Component {
if (files && files.length !== 0) {
console.log(files[0]);
const name = files[0].name;
- const formData = new FormData();
- formData.append("file", files[0]);
-
- const upload = window.location.origin + "/uploadFormData";
+ const res = await Networking.UploadFilesToServer(files[0]);
this.status = "uploading image";
- console.log("uploading image", formData);
- const res = await fetch(upload, {
- method: 'POST',
- body: formData
- });
this.status = "upload image, getting json";
- const json = await res.json();
- json.map(async (file: any) => {
- const path = window.location.origin + file;
+
+ res.map(async ({ result }) => {
+ if (result instanceof Error) {
+ return;
+ }
+ const path = Utils.prepend(result.accessPaths.agnostic.client);
const doc = Docs.Create.ImageDocument(path, { _nativeWidth: 200, _width: 200, title: name });
this.status = "getting user document";
@@ -75,12 +73,10 @@ class Uploader extends React.Component {
pending.data = new List([doc]);
}
this.status = "finished";
+ console.log("hi");
}
- });
-
- // console.log(window.location.origin + file[0])
- //imgPrev.setAttribute("src", window.location.origin + files[0].name)
+ });
}
}
} catch (error) {
@@ -91,12 +87,12 @@ class Uploader extends React.Component {
render() {
return (
<div className="imgupload_cont">
- <label htmlFor="input_image_file" className="upload_label">Choose an Image</label>
+ <label htmlFor="input_image_file" className="upload_label" onClick={this.onClick}>Upload Image</label>
<input type="file" accept="image/*" className="input_file" id="input_image_file" ref={inputRef}></input>
- <button onClick={this.onClick} className="upload_button">Upload</button>
+ {/* <div onClick={this.onClick} className="upload_button">Upload</div> */}
<img id="img_preview" src=""></img>
<p>{this.status}</p>
- <p>{this.error}</p>
+ {/* <p>{this.error}</p> */}
</div>
);
}
@@ -104,25 +100,4 @@ class Uploader extends React.Component {
}
-// DocServer.init(window.location.protocol, window.location.hostname, resolvedPorts.socket, "image upload");
-(async () => {
- const info = await CurrentUserUtils.loadCurrentUser();
- DocServer.init(window.location.protocol, window.location.hostname, resolvedPorts.socket, info.email + "mobile");
- await Docs.Prototypes.initialize();
- if (info.id !== "__guest__") {
- // a guest will not have an id registered
- await CurrentUserUtils.loadUserDocument(info);
- }
- document.getElementById('root')!.addEventListener('wheel', event => {
- if (event.ctrlKey) {
- event.preventDefault();
- }
- }, true);
- ReactDOM.render((
- // <Uploader />
- <MobileInterface />
- ),
- document.getElementById('root')
- );
-}
-)(); \ No newline at end of file
+// DocServer.init(window.location.protocol, window.location.hostname, 4321, "image upload"); \ No newline at end of file
diff --git a/src/mobile/MobileInterface.scss b/src/mobile/MobileInterface.scss
index 4d86e208f..f75e60a37 100644
--- a/src/mobile/MobileInterface.scss
+++ b/src/mobile/MobileInterface.scss
@@ -16,4 +16,13 @@
height: 100%;
position: relative;
touch-action: none;
+ width: 100%;
+}
+
+.mobileInterface-background {
+ height: 100%;
+ width: 100%;
+ position: relative;
+ touch-action: none;
+ background-color: pink;
} \ No newline at end of file
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index 6c2e797d6..9b28d066c 100644
--- a/src/mobile/MobileInterface.tsx
+++ b/src/mobile/MobileInterface.tsx
@@ -1,47 +1,68 @@
import React = require('react');
import { library } from '@fortawesome/fontawesome-svg-core';
-import { faEraser, faHighlighter, faLongArrowAltLeft, faMousePointer, faPenNib } from '@fortawesome/free-solid-svg-icons';
+import { faEraser, faHighlighter, faLongArrowAltLeft, faMousePointer, faPenNib, faThumbtack, faHome } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, observable } from 'mobx';
import { observer } from 'mobx-react';
-import { DocServer } from '../client/DocServer';
+import * as ReactDOM from "react-dom";
+import * as rp from 'request-promise';
+import { CurrentUserUtils } from '../client/util/CurrentUserUtils';
+import { FieldValue, Cast, StrCast } from '../fields/Types';
+import { Doc, DocListCast, Opt } from '../fields/Doc';
import { Docs } from '../client/documents/Documents';
-import { DocumentManager } from '../client/util/DocumentManager';
-import RichTextMenu from '../client/views/nodes/formattedText/RichTextMenu';
-import { Scripting } from '../client/util/Scripting';
+import { CollectionView } from '../client/views/collections/CollectionView';
+import { DocumentView } from '../client/views/nodes/DocumentView';
+import { emptyPath, emptyFunction, returnFalse, returnOne, returnEmptyString, returnTrue, returnZero, Utils } from '../Utils';
import { Transform } from '../client/util/Transform';
-import { DocumentDecorations } from '../client/views/DocumentDecorations';
+import { Scripting } from '../client/util/Scripting';
import GestureOverlay from '../client/views/GestureOverlay';
import { InkingControl } from '../client/views/InkingControl';
-import { DocumentView } from '../client/views/nodes/DocumentView';
-import { RadialMenu } from '../client/views/nodes/RadialMenu';
+import { InkTool } from '../fields/InkField';
+import "./MobileInterface.scss";
+import "./MobileMenu.scss";
+import { DocServer } from '../client/DocServer';
+import { DocumentDecorations } from '../client/views/DocumentDecorations';
import { PreviewCursor } from '../client/views/PreviewCursor';
-import { Doc, DocListCast, FieldResult } from '../fields/Doc';
+import { RadialMenu } from '../client/views/nodes/RadialMenu';
import { Id } from '../fields/FieldSymbols';
-import { InkTool } from '../fields/InkField';
+import { WebField, nullAudio } from "../fields/URLField";
+import { FieldResult } from "../fields/Doc";
+import { AssignAllExtensions } from '../extensions/General/Extensions';
import { listSpec } from '../fields/Schema';
-import { Cast, FieldValue } from '../fields/Types';
-import { WebField } from "../fields/URLField";
-import { CurrentUserUtils } from '../client/util/CurrentUserUtils';
-import { emptyFunction, emptyPath, returnEmptyString, returnFalse, returnOne, returnTrue, returnZero } from '../Utils';
-import "./MobileInterface.scss";
-import { CollectionView } from '../client/views/collections/CollectionView';
+import { DocumentManager } from '../client/util/DocumentManager';
+import RichTextMenu from '../client/views/nodes/formattedText/RichTextMenu';
+import { MainView } from '../client/views/MainView';
+import SettingsManager from '../client/util/SettingsManager';
+import { Uploader } from "./ImageUpload";
+import { Upload } from '../server/SharedMediaTypes';
+import { createTypePredicateNodeWithModifier } from 'typescript';
+import { AudioBox } from '../client/views/nodes/AudioBox';
+import { List } from '../fields/List';
library.add(faLongArrowAltLeft);
+library.add(faHome);
@observer
-export default class MobileInterface extends React.Component {
+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";
- private mainDoc: any = CurrentUserUtils.setupMobileDoc(this.userDoc);
+ @observable private mainDoc: any = CurrentUserUtils.setupMobileMenu(this.userDoc);
@observable private renderView?: () => JSX.Element;
+ public _activeDoc: Doc = this.mainDoc;
+
// private inkDoc?: Doc;
public drawingInk: boolean = false;
- // private uploadDoc?: Doc;
+ // private _uploadDoc: Doc = this.userDoc;
+ private _child: Doc | null = null;
+ private _parents: Array<Doc> = [];
+ private _menu: Doc = this.mainDoc;
+ private _open: boolean = false;
+ private _library: Doc = Cast(this.userDoc.myWorkspaces, Doc) as Doc;
constructor(props: Readonly<{}>) {
super(props);
@@ -50,7 +71,7 @@ export default class MobileInterface extends React.Component {
@action
componentDidMount = () => {
- library.add(...[faPenNib, faHighlighter, faEraser, faMousePointer]);
+ library.add(...[faPenNib, faHighlighter, faEraser, faMousePointer, faThumbtack]);
if (this.userDoc && !this.mainContainer) {
this.userDoc.activeMobile = this.mainDoc;
@@ -81,6 +102,7 @@ export default class MobileInterface extends React.Component {
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) {
@@ -102,34 +124,286 @@ export default class MobileInterface extends React.Component {
});
}
- renderDefaultContent = () => {
+ toggleSidebar = () => {
+ 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 = "menu";
+ }
+ }
+
+ back = () => {
+ let doc = Cast(this._parents.pop(), Doc) as Doc;
+ if (doc == Cast(this._menu, Doc) as Doc) {
+ this._child = null;
+ this.userDoc.activeMobile = this.mainDoc;
+ } else {
+ if (doc) {
+ this._child = doc;
+ this.switchCurrentView((userDoc: Doc) => doc);
+ }
+ }
+ if (doc) {
+ this._activeDoc = doc;
+ }
+ }
+
+ returnHome = () => {
+ this._parents = [];
+ this._activeDoc = this._menu;
+ this.switchCurrentView((userDoc: Doc) => this._menu);
+ this._child = null;
+ }
+
+ displayWorkspaces = () => {
if (this.mainContainer) {
- return <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} />;
+ const backgroundColor = () => "white";
+ return (
+ <div style={{ position: "relative", top: '200px', height: `calc(100% - 250px)`, width: "80%", overflow: "hidden", left: "10%" }}>
+ <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>
+ );
+ }
+ }
+
+ 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.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._child = doc;
+ }
+
+ // let sidebar = document.getElementById("sidebar") as HTMLElement;
+ // sidebar.classList.toggle('active');
+ }
+
+ createPathname = () => {
+ let pathname = "";
+ this._parents.map((doc: Doc, index: any) => {
+ if (doc === this.mainDoc) {
+ pathname = pathname + doc.title;
+ } else {
+ pathname = pathname + " > " + doc.title;
+ }
+ });
+ if (this._activeDoc === this.mainDoc) {
+ pathname = pathname + this._activeDoc.title;
+ } else {
+ pathname = pathname + " > " + this._activeDoc.title;
+ }
+ return pathname;
+ }
+
+ openLibrary() {
+ this._activeDoc = this.mainDoc;
+ this.switchCurrentView((userDoc: Doc) => this.mainDoc);
+ this._child = this._library;
+ }
+
+ renderDefaultContent = () => {
+ const workspaces = Cast(this.userDoc.myWorkspaces, Doc) as Doc;
+ let buttons = DocListCast(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>);
+ });
+
+ if (this._child) {
+ buttons = DocListCast(this._child.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>);
+ });
+ }
+
+ if (!this._child) {
+ return (
+ <div>
+ <div className="navbar">
+ <div className="header" id="header">MENU</div>
+ <div className="toggle-btn" id="menuButton" onClick={this.toggleSidebar}>
+ <span></span>
+ <span></span>
+ <span></span>
+ </div>
+ </div>
+ <div className="pathbar">
+ <div className="pathname">
+ {this.createPathname()}
+ </div>
+ </div>
+ <div className="sidebar" id="sidebar">
+ <div>
+ <FontAwesomeIcon className="home" icon="home" onClick={this.returnHome} />
+ {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.openDefaultPresentation}>
+ Presentation
+ </div>
+ <div className="item" key="settings" onClick={() => SettingsManager.Instance.open()}>
+ Settings
+ </div>
+ </div>
+ </div>
+ <div>
+ {this.renderView}
+ </div>
+ </div>
+ );
+ }
+ else {
+ return (
+ <div>
+ <div className="navbar">
+ <div className="header" id="header">menu</div>
+ <div className="toggle-btn" id="menuButton" onClick={this.toggleSidebar}>
+ <span></span>
+ <span></span>
+ <span></span>
+ </div>
+ </div>
+ <div className="pathbar">
+ <div className="pathname">
+ {this.createPathname()}
+ </div>
+ </div>
+ <div className="sidebar" id="sidebar">
+ <FontAwesomeIcon className="home" icon="home" onClick={this.returnHome} />
+ <div className="back" onClick={this.back}>
+ &#8592;
+ </div>
+ <div>
+ {buttons}
+ </div>
+ <div className="item" key="home" onClick={this.returnHome}>
+ Home
+ </div>
+ </div>
+ </div>
+ );
+ }
+ }
+
+ recordAudio = async () => {
+ // upload to server with known URL
+
+ const audioDoc = Cast(Docs.Create.AudioDocument(nullAudio, { _width: 200, _height: 100, title: "mobile audio" }), Doc) as Doc;
+ if (audioDoc) {
+ console.log("audioClicked: " + audioDoc.title);
+ this._activeDoc = audioDoc;
+ this.switchCurrentView((userDoc: Doc) => audioDoc);
+ this.toggleSidebar();
+ }
+ const audioRightSidebar = Cast(Doc.UserDoc().rightSidebarCollection, Doc) as Doc;
+ if (audioRightSidebar) {
+ console.log(audioRightSidebar.title);
+ const data = Cast(audioRightSidebar.data, listSpec(Doc));
+ if (data) {
+ data.push(audioDoc);
+ }
+ }
+ }
+
+ openDefaultPresentation = () => {
+ const presentation = Cast(Doc.UserDoc().activePresentation, Doc) as Doc;
+
+ if (presentation) {
+ console.log("presentation clicked: " + presentation.title);
+ this._activeDoc = presentation;
+ this.switchCurrentView((userDoc: Doc) => presentation);
+ 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>
+ );
+ }
}
- return "hello";
}
onBack = (e: React.MouseEvent) => {
@@ -164,60 +438,15 @@ export default class MobileInterface extends React.Component {
panelHeight = () => window.innerHeight;
panelWidth = () => window.innerWidth;
- 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>
- );
- }
- }
+ //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 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
@@ -259,46 +488,6 @@ export default class MobileInterface extends React.Component {
}
}
}
-
- 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>
- );
- }
- }
-
onDragOver = (e: React.DragEvent) => {
e.preventDefault();
e.stopPropagation();
@@ -314,18 +503,21 @@ export default class MobileInterface extends React.Component {
<GestureOverlay>
{this.renderView ? this.renderView() : this.renderDefaultContent()}
</GestureOverlay> */}
-
+ {/* <GestureOverlay> */}
+ <SettingsManager />
+ {this.displayWorkspaces()}
+ {/* </GestureOverlay> */}
{/* <DictationOverlay />
<SharingManager />
<GoogleAuthenticationManager /> */}
- <DocumentDecorations />
- <GestureOverlay>
- {this.renderView ? this.renderView() : this.renderDefaultContent()}
- </GestureOverlay>
- <PreviewCursor />
+ {/* <DocumentDecorations /> */}
+ <div>
+ {this.renderDefaultContent()}
+ </div>
+ {/* <PreviewCursor /> */}
{/* <ContextMenu /> */}
- <RadialMenu />
- <RichTextMenu />
+ {/* <RadialMenu />
+ <RichTextMenu /> */}
{/* <PDFMenu />
<MarqueeOptionsMenu />
<OverlayView /> */}
@@ -335,9 +527,121 @@ export default 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 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(); });
+// WAS 2
+
+AssignAllExtensions();
+
+(async () => {
+ const info = await CurrentUserUtils.loadCurrentUser();
+ DocServer.init(window.location.protocol, window.location.hostname, 4321, info.email + " (mobile)");
+ await Docs.Prototypes.initialize();
+ if (info.id !== "__guest__") {
+ // a guest will not have an id registered
+ await CurrentUserUtils.loadUserDocument(info);
+ }
+ document.getElementById('root')!.addEventListener('wheel', event => {
+ if (event.ctrlKey) {
+ event.preventDefault();
+ }
+ }, true);
+ ReactDOM.render(<MobileInterface />, document.getElementById('root'));
+})();
+
+
+// 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>
+ // );
+ // }
+ // } \ No newline at end of file
diff --git a/src/mobile/MobileMenu.scss b/src/mobile/MobileMenu.scss
new file mode 100644
index 000000000..250340e36
--- /dev/null
+++ b/src/mobile/MobileMenu.scss
@@ -0,0 +1,240 @@
+$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;
+ border-bottom: 5px solid black;
+}
+
+.navbar .toggle-btn {
+ position: absolute;
+ right: 20px;
+ top: 30px;
+ height: 70px;
+ width: 70px;
+ transition: all 300ms ease-in-out 200ms;
+}
+
+.navbar .header {
+ position: absolute;
+ top: 50%;
+ top: calc(9px + 50%);
+ right: 50%;
+ transform: translate(50%, -50%);
+ font-size: 40;
+ user-select: none;
+ text-transform: uppercase;
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+.navbar .toggle-btn span {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ width: 70%;
+ height: 4px;
+ background: black;
+ transition: all 200ms ease;
+}
+
+.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: absolute;
+ top: 200px;
+ opacity: 0;
+ right: -100%;
+ width: 100%;
+ height: calc(100% - (200px));
+ z-index: 5;
+ background-color: whitesmoke;
+ transition: all 400ms ease 50ms;
+ padding: 20px;
+ // border-right: 5px solid black;
+}
+
+.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;
+ font-size: 35px;
+ text-transform: uppercase;
+ color: black;
+}
+
+.sidebar .home {
+ position: absolute;
+ top: -135px;
+ right: calc(50% + 80px);
+ transform: translate(0%, -50%);
+ font-size: 40;
+ user-select: none;
+ text-transform: uppercase;
+ font-family: Arial, Helvetica, sans-serif;
+ z-index: 200;
+}
+
+.type {
+ display: inline;
+ text-transform: lowercase;
+ margin-left: 20px;
+ font-size: 35px;
+ font-style: italic;
+ color: rgb(28, 28, 28);
+}
+
+.right {
+ margin-left: 20px;
+ z-index: 200;
+}
+
+.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 {
+ right: 0%;
+ opacity: 1;
+}
+
+.back {
+ position: absolute;
+ top: -140px;
+ left: 50px;
+ transform: translate(0%, -50%);
+ color: black;
+ font-size: 60;
+ user-select: none;
+ text-transform: uppercase;
+ z-index: 100;
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+
+.pathbar {
+ position: absolute;
+ top: 118px;
+ background: #1a1a1a;
+ z-index: 20;
+ border-radius: 0px;
+ width: 100%;
+ height: 80px;
+ transition: all 400ms ease 50ms;
+}
+
+.pathname {
+ position: relative;
+ font-size: 25;
+ top: 50%;
+ width: 90%;
+ left: 3%;
+ 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;
+}
+
+.homeContainer {
+ position: relative;
+ top: 200px;
+ height: calc(100% - 250px);
+ width: 90%;
+ overflow: scroll;
+ left: 5%;
+ background-color: lightpink;
+}
+
+.pinButton {
+ position: relative;
+ width: 100px;
+ height: 100px;
+ font-size: 90px;
+ text-align: center;
+ left: 50%;
+ transform: translate(-50%, 0);
+ border-style: solid;
+ border-radius: 50px;
+ border-width: medium;
+ background-color: pink;
+ z-index: 100;
+} \ No newline at end of file
diff --git a/webpack.config.js b/webpack.config.js
index bd1d3b5a9..274f14069 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -43,7 +43,7 @@ module.exports = {
repl: ["./src/debug/Repl.tsx", 'webpack-hot-middleware/client?reload=true'],
test: ["./src/debug/Test.tsx", 'webpack-hot-middleware/client?reload=true'],
inkControls: ["./src/mobile/InkControls.tsx", 'webpack-hot-middleware/client?reload=true'],
- imageUpload: ["./src/mobile/ImageUpload.tsx", 'webpack-hot-middleware/client?reload=true'],
+ mobileInterface: ["./src/mobile/MobileInterface.tsx", 'webpack-hot-middleware/client?reload=true'],
},
optimization: {
noEmitOnErrors: true