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 /src | |
parent | cdc9c7e293a656573d49c4265b5867e34e8db7c8 (diff) |
initial commit
Diffstat (limited to 'src')
-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 |
11 files changed, 851 insertions, 214 deletions
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 |