diff options
author | Sam Wilkins <samwilkins333@gmail.com> | 2020-06-06 00:04:54 -0700 |
---|---|---|
committer | Sam Wilkins <samwilkins333@gmail.com> | 2020-06-06 00:04:54 -0700 |
commit | 1a6feb447f9c4fd461ba02dc45a93e569a283be0 (patch) | |
tree | 2cadb27d639656f51ee7820589fe62cbf1716300 | |
parent | cdc9c7e293a656573d49c4265b5867e34e8db7c8 (diff) |
initial commit
-rw-r--r-- | deploy/mobile/image.html | 2 | ||||
-rw-r--r-- | package-lock.json | 84 | ||||
-rw-r--r-- | src/mobile/ImageUpload.scss | 55 | ||||
-rw-r--r-- | src/mobile/ImageUpload.tsx | 74 | ||||
-rw-r--r-- | src/mobile/MobileInkOverlay.tsx | 4 | ||||
-rw-r--r-- | src/mobile/MobileInterface.scss | 9 | ||||
-rw-r--r-- | src/mobile/MobileInterface.tsx | 526 | ||||
-rw-r--r-- | src/mobile/MobileMain.tsx | 25 | ||||
-rw-r--r-- | src/mobile/MobileMenu.scss | 240 | ||||
-rw-r--r-- | src/mobile/SideBar.scss | 79 | ||||
-rw-r--r-- | src/mobile/SideBar.tsx | 39 | ||||
-rw-r--r-- | src/mobile/WorkSpaceButton.scss | 0 | ||||
-rw-r--r-- | src/mobile/WorkSpaceButton.tsx | 14 | ||||
-rw-r--r-- | webpack.config.js | 64 |
14 files changed, 936 insertions, 279 deletions
diff --git a/deploy/mobile/image.html b/deploy/mobile/image.html index 6424d2a60..beca8b68b 100644 --- a/deploy/mobile/image.html +++ b/deploy/mobile/image.html @@ -9,7 +9,7 @@ <div id="root"> <p>Capture Image: <input type="file" accept="image/*" id="capture"> </div> - <script src="../imageUpload.js"></script> + <script src="../mobileInterface.js"></script> </body> </html>
\ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 842553659..6ee723aab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2827,7 +2827,8 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "bundled": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -2845,11 +2846,13 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true + "bundled": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2862,15 +2865,18 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "concat-map": { "version": "0.0.1", - "bundled": true + "bundled": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -2973,7 +2979,8 @@ }, "inherits": { "version": "2.0.4", - "bundled": true + "bundled": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -2983,6 +2990,7 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -2995,17 +3003,20 @@ "minimatch": { "version": "3.0.4", "bundled": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "1.2.5", - "bundled": true + "bundled": true, + "optional": true }, "minipass": { "version": "2.9.0", "bundled": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -3022,6 +3033,7 @@ "mkdirp": { "version": "0.5.3", "bundled": true, + "optional": true, "requires": { "minimist": "^1.2.5" } @@ -3077,7 +3089,8 @@ }, "npm-normalize-package-bin": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "npm-packlist": { "version": "1.4.8", @@ -3102,7 +3115,8 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -3112,6 +3126,7 @@ "once": { "version": "1.4.0", "bundled": true, + "optional": true, "requires": { "wrappy": "1" } @@ -3180,7 +3195,8 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true + "bundled": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -3210,6 +3226,7 @@ "string-width": { "version": "1.0.2", "bundled": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3227,6 +3244,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3265,11 +3283,13 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "yallist": { "version": "3.1.1", - "bundled": true + "bundled": true, + "optional": true } } } @@ -9486,7 +9506,7 @@ }, "chownr": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "resolved": false, "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "ci-info": { @@ -9792,7 +9812,7 @@ }, "deep-extend": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "resolved": false, "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, "defaults": { @@ -10291,7 +10311,7 @@ }, "glob": { "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "resolved": false, "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "requires": { "fs.realpath": "^1.0.0", @@ -10379,7 +10399,7 @@ }, "hosted-git-info": { "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "resolved": false, "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" }, "http-cache-semantics": { @@ -10515,7 +10535,7 @@ }, "is-ci": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "resolved": false, "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", "requires": { "ci-info": "^1.5.0" @@ -10591,7 +10611,7 @@ }, "is-retry-allowed": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "resolved": false, "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==" }, "is-stream": { @@ -11100,7 +11120,7 @@ }, "mkdirp": { "version": "0.5.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", + "resolved": false, "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", "requires": { "minimist": "^1.2.5" @@ -11108,7 +11128,7 @@ "dependencies": { "minimist": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "resolved": false, "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" } } @@ -11160,7 +11180,7 @@ }, "node-gyp": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-5.1.0.tgz", + "resolved": false, "integrity": "sha512-OUTryc5bt/P8zVgNUmC6xdXiDJxLMAW8cF5tLQOT9E5sOQj+UeQxnnPy74K3CLCa/SOjjBlbuzDLR8ANwA+wmw==", "requires": { "env-paths": "^2.2.0", @@ -11274,7 +11294,7 @@ }, "npm-packlist": { "version": "1.4.8", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "resolved": false, "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", "requires": { "ignore-walk": "^3.0.1", @@ -11294,7 +11314,7 @@ }, "npm-profile": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/npm-profile/-/npm-profile-4.0.4.tgz", + "resolved": false, "integrity": "sha512-Ta8xq8TLMpqssF0H60BXS1A90iMoM6GeKwsmravJ6wYjWwSzcYBTdyWa3DZCYqPutacBMEm7cxiOkiIeCUAHDQ==", "requires": { "aproba": "^1.1.2 || 2", @@ -11304,7 +11324,7 @@ }, "npm-registry-fetch": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.3.tgz", + "resolved": false, "integrity": "sha512-WGvUx0lkKFhu9MbiGFuT9nG2NpfQ+4dCJwRwwtK2HK5izJEvwDxMeUyqbuMS7N/OkpVCqDorV6rO5E4V9F8lJw==", "requires": { "JSONStream": "^1.3.4", @@ -11739,7 +11759,7 @@ }, "rc": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "resolved": false, "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "requires": { "deep-extend": "^0.6.0", @@ -11750,7 +11770,7 @@ "dependencies": { "minimist": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "resolved": false, "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" } } @@ -11809,7 +11829,7 @@ }, "readable-stream": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "resolved": false, "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "requires": { "inherits": "^2.0.3", @@ -11830,7 +11850,7 @@ }, "registry-auth-token": { "version": "3.4.0", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", + "resolved": false, "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", "requires": { "rc": "^1.1.6", @@ -11894,7 +11914,7 @@ }, "rimraf": { "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "resolved": false, "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "requires": { "glob": "^7.1.3" @@ -12193,7 +12213,7 @@ }, "string_decoder": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "resolved": false, "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "requires": { "safe-buffer": "~5.2.0" @@ -12201,7 +12221,7 @@ "dependencies": { "safe-buffer": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "resolved": false, "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" } } @@ -12513,7 +12533,7 @@ }, "widest-line": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "resolved": false, "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", "requires": { "string-width": "^2.1.1" diff --git a/src/mobile/ImageUpload.scss b/src/mobile/ImageUpload.scss index eea69b81c..6ebf33438 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..c35c4a917 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -4,16 +4,18 @@ 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 { 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 { Doc, Opt } from '../fields/Doc'; +import { Cast } from '../fields/Types'; +import { listSpec } from '../fields/Schema'; +import { List } from '../fields/List'; + +export interface ImageUploadProps { + Document: Doc; +} // const onPointerDown = (e: React.TouchEvent) => { // let imgInput = document.getElementById("input_image_file"); @@ -24,7 +26,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 +41,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 +72,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 +86,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.status}</p> + <p>{this.error}</p> */} </div> ); } @@ -104,25 +99,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"); diff --git a/src/mobile/MobileInkOverlay.tsx b/src/mobile/MobileInkOverlay.tsx index 973931615..1b3388161 100644 --- a/src/mobile/MobileInkOverlay.tsx +++ b/src/mobile/MobileInkOverlay.tsx @@ -4,11 +4,9 @@ import { MobileInkOverlayContent, GestureContent, UpdateMobileInkOverlayPosition import { observable, action } from "mobx"; import { GestureUtils } from "../pen-gestures/GestureUtils"; import "./MobileInkOverlay.scss"; -import { StrCast, Cast } from '../fields/Types'; import { DragManager } from "../client/util/DragManager"; import { DocServer } from '../client/DocServer'; -import { Doc, DocListCastAsync } from '../fields/Doc'; -import { listSpec } from '../fields/Schema'; +import { Doc } from '../fields/Doc'; @observer 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..1f7244653 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -1,47 +1,56 @@ 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 rp from 'request-promise'; 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 { DocumentView } from '../client/views/nodes/DocumentView'; +import { emptyPath, emptyFunction, returnFalse, returnOne, returnTrue, returnZero, Utils } from '../Utils'; import { Transform } from '../client/util/Transform'; -import { DocumentDecorations } from '../client/views/DocumentDecorations'; -import GestureOverlay from '../client/views/GestureOverlay'; +import { Scripting } from '../client/util/Scripting'; import { InkingControl } from '../client/views/InkingControl'; -import { DocumentView } from '../client/views/nodes/DocumentView'; -import { RadialMenu } from '../client/views/nodes/RadialMenu'; -import { PreviewCursor } from '../client/views/PreviewCursor'; +import "./MobileInterface.scss"; +import "./MobileMenu.scss"; +import { DocServer } from '../client/DocServer'; +import { DocumentManager } from '../client/util/DocumentManager'; +import SettingsManager from '../client/util/SettingsManager'; +import { Uploader } from "./ImageUpload"; +import { DockedFrameRenderer } from '../client/views/collections/CollectionDockingView'; import { Doc, DocListCast, FieldResult } from '../fields/Doc'; -import { Id } from '../fields/FieldSymbols'; +import { FieldValue, Cast, StrCast } from '../fields/Types'; import { InkTool } from '../fields/InkField'; import { listSpec } from '../fields/Schema'; -import { Cast, FieldValue } from '../fields/Types'; -import { WebField } from "../fields/URLField"; +import { nullAudio, WebField } from '../fields/URLField'; +import { Id } from '../fields/FieldSymbols'; 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'; 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.setupMobileDoc(this.userDoc); @observable private renderView?: () => JSX.Element; + @observable private sidebarActive = true; + + 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 +59,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 +90,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 +112,243 @@ export default class MobileInterface extends React.Component { }); } - renderDefaultContent = () => { + back = () => { + const 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: "100%", overflow: "hidden" }}> + <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) { + const 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; + } + + @action + toggleSidebar = () => this.sidebarActive = !this.sidebarActive + + openLibrary() { + this._activeDoc = this.mainDoc; + this.switchCurrentView(() => this.mainDoc); + this._child = this._library; + } + + renderDefaultContent = () => { + const workspaces = Cast(this.userDoc.myWorkspaces, Doc) as Doc; + const buttons = DocListCast(this._child ? this._child.data : workspaces.data).map((doc: Doc, index: any) => { + return ( + <div + className="item" + key={index} + onClick={() => this.handleClick(doc)}>{doc.title} + <div className="type">{doc.type}</div> + <FontAwesomeIcon className="right" icon="angle-right" size="lg" /> + </div>); + }); + return ( + <> + <div className="navbar"> + <div className={"header"}>{this.sidebarActive ? StrCast(this._activeDoc.title) : "Menu"}</div> + <div + className={`toggle-btn ${this.sidebarActive ? "active" : ""}`} + onClick={this.toggleSidebar} + /> + </div> + <div className="pathbar"> + <div className="pathname">{this.createPathname()}</div> + </div> + <div className={`sidebar ${this.sidebarActive ? "active" : ""}`}> + <FontAwesomeIcon className="home" icon="home" onClick={this.returnHome} /> + {this._child ? + <> + <div className="back" onClick={this.back}>←</div> + <div>{buttons}</div> + <div className="item" key="home" onClick={this.returnHome}>Home</div> + </> : + <> + {buttons} + {/* <div className="item" key="library" onClick={this.openLibrary}> + Library + </div> */} + <Uploader Document={workspaces} /> + <div className="item" key="audio" onClick={this.recordAudio}>Record Audio</div> + <div className="item" key="presentation" onClick={this.openDefaultPresentation}>Presentation</div> + <div className="item" key="settings" onClick={() => SettingsManager.Instance.open()}>Settings</div> + </> + } + </div> + {this._child ? null : <div>{this.renderView}</div>} + </> + ); + } + + pinToPresentation = () => { + // Only making button available if it is an image + if (this._activeDoc.type === "image") { + const isPinned = this._activeDoc && Doc.isDocPinned(this._activeDoc); + return <div className="pinButton" + title={Doc.isDocPinned(this._activeDoc) ? "Unpin from presentation" : "Pin to presentation"} + style={{ backgroundColor: isPinned ? "black" : "white", color: isPinned ? "white" : "black" }} + onClick={e => { + if (isPinned) { + DockedFrameRenderer.UnpinDoc(this._activeDoc); + } + else { + DockedFrameRenderer.PinDoc(this._activeDoc); + } + }}> + <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin" + /> + </div>; + } + } + + recordAudio = async () => { + // upload to server with known URL + this._parents.push(this._activeDoc); + 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 = () => { + this._parents.push(this._activeDoc); + 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 +383,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 @@ -260,45 +434,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 +449,22 @@ export default class MobileInterface extends React.Component { <GestureOverlay> {this.renderView ? this.renderView() : this.renderDefaultContent()} </GestureOverlay> */} - + {/* <GestureOverlay> */} + <SettingsManager /> + {this.displayWorkspaces()} + {this.pinToPresentation()} + {/* </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 +474,102 @@ 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 + +// 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> + // ); + // } + // } diff --git a/src/mobile/MobileMain.tsx b/src/mobile/MobileMain.tsx new file mode 100644 index 000000000..34f06438f --- /dev/null +++ b/src/mobile/MobileMain.tsx @@ -0,0 +1,25 @@ +import { DocServer } from '../client/DocServer'; +import { Docs } from '../client/documents/Documents'; +import * as ReactDOM from "react-dom"; +import { MobileInterface } from './MobileInterface'; +import * as React from "react"; +import { AssignAllExtensions } from '../extensions/General/Extensions'; +import { CurrentUserUtils } from '../client/util/CurrentUserUtils'; + +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')); +})();
\ 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/src/mobile/SideBar.scss b/src/mobile/SideBar.scss new file mode 100644 index 000000000..fb6d13a2b --- /dev/null +++ b/src/mobile/SideBar.scss @@ -0,0 +1,79 @@ +* { + 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:50px; + background:rgba(0,0,0,0.95); +} +.navbar .toggle-btn { + position:absolute; + right:20px; + height:50px; + width:50px; + transition:all 300ms ease-in-out 200ms; +} +.navbar .toggle-btn span { + position:absolute; + top:50%; + left:50%; + transform:translate(-50%,-50%); + width:70%; + height:4px; + background:#eee; + 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:50px; + opacity:0; + right:-100%; + width:100vw; + height:calc(100vh - 45px); + z-index:5; + background:rgba(40,40,40,1); + transition:all 400ms ease 50ms; + padding:15px; +} +.sidebar .item { + width:100%; + padding:13px 6px; + border-bottom:1px solid rgba(200,200,200,0.7); + font-size:18px; + text-transform:uppercase; + color:rgba(250,250,250,0.95); +} +.sidebar.active { + right:0%; + opacity:1; +}
\ No newline at end of file diff --git a/src/mobile/SideBar.tsx b/src/mobile/SideBar.tsx new file mode 100644 index 000000000..a06069ed8 --- /dev/null +++ b/src/mobile/SideBar.tsx @@ -0,0 +1,39 @@ +import React = require("react"); +import { observer } from "mobx-react"; +import "./SideBar.scss"; +import { computed } from "mobx"; +import { DocumentView } from '../client/views/nodes/DocumentView'; + +@observer +export class SideBar extends React.Component<{ views: (DocumentView | undefined)[], stack?: any }, {}>{ + + constructor(props: { views: (DocumentView | undefined)[] }) { + super(props); + } + + @computed + onClick() { + document.getElementsByClassName('sidebar') + [0].classList.toggle('active'); + } + + render() { + return ( + <> + <div className="navbar"> + <div className="toggle-btn" onClick={this.onClick}> + <span></span> + <span></span> + <span></span> + </div> + </div> + <div className="sidebar"> + <div className="item">Workspace1</div> + <div className="item">Workspace2</div> + <div className="item">Workspace3</div> + </div> + </> + ); + } + +}
\ No newline at end of file diff --git a/src/mobile/WorkSpaceButton.scss b/src/mobile/WorkSpaceButton.scss new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/mobile/WorkSpaceButton.scss diff --git a/src/mobile/WorkSpaceButton.tsx b/src/mobile/WorkSpaceButton.tsx new file mode 100644 index 000000000..70c3e6edc --- /dev/null +++ b/src/mobile/WorkSpaceButton.tsx @@ -0,0 +1,14 @@ +import React = require('react'); +import { observer } from "mobx-react"; +import { observable } from 'mobx'; + +interface IProps { + open: boolean; +} + +@observer +export class MenuButton extends React.Component<IProps> { + @observable static Instance: MenuButton; + + +}
\ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index bd1d3b5a9..a5fe6ad80 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/MobileMain.tsx", 'webpack-hot-middleware/client?reload=true'], }, optimization: { noEmitOnErrors: true @@ -66,42 +66,42 @@ module.exports = { }, module: { rules: [{ - test: [/\.tsx?$/], - use: [{ - loader: 'ts-loader', - options: { - transpileOnly: true - } - }] - }, - { - test: /\.scss|css$/, - use: [{ - loader: "style-loader" + test: [/\.tsx?$/], + use: [{ + loader: 'ts-loader', + options: { + transpileOnly: true + } + }] }, { - loader: "css-loader" + test: /\.scss|css$/, + use: [{ + loader: "style-loader" + }, + { + loader: "css-loader" + }, + { + loader: "sass-loader" + } + ] }, { - loader: "sass-loader" + test: /\.(jpg|png|pdf)$/, + use: [{ + loader: 'file-loader' + }] + }, + { + test: /\.(png|jpg|gif)$/i, + use: [{ + loader: 'url-loader', + options: { + limit: 8192 + } + }] } - ] - }, - { - test: /\.(jpg|png|pdf)$/, - use: [{ - loader: 'file-loader' - }] - }, - { - test: /\.(png|jpg|gif)$/i, - use: [{ - loader: 'url-loader', - options: { - limit: 8192 - } - }] - } ] }, plugins, |