import React = require('react'); import { library } from '@fortawesome/fontawesome-svg-core'; 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 * as rp from 'request-promise'; import { Docs } from '../client/documents/Documents'; import { DocumentView } from '../client/views/nodes/DocumentView'; import { emptyPath, emptyFunction, returnFalse, returnOne, returnTrue, returnZero, Utils } from '../Utils'; import { Transform } from '../client/util/Transform'; import { Scripting } from '../client/util/Scripting'; import { InkingControl } from '../client/views/InkingControl'; 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 { FieldValue, Cast, StrCast } from '../fields/Types'; import { InkTool } from '../fields/InkField'; import { listSpec } from '../fields/Schema'; import { nullAudio, WebField } from '../fields/URLField'; import { Id } from '../fields/FieldSymbols'; import { CurrentUserUtils } from '../client/util/CurrentUserUtils'; library.add(faLongArrowAltLeft); library.add(faHome); @observer 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"; @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 = this.userDoc; private _child: Doc | null = null; private _parents: Array = []; private _menu: Doc = this.mainDoc; private _open: boolean = false; private _library: Doc = Cast(this.userDoc.myWorkspaces, Doc) as Doc; constructor(props: Readonly<{}>) { super(props); MobileInterface.Instance = this; } @action componentDidMount = () => { library.add(...[faPenNib, faHighlighter, faEraser, faMousePointer, faThumbtack]); if (this.userDoc && !this.mainContainer) { this.userDoc.activeMobile = this.mainDoc; } } @action switchCurrentView = (doc: (userDoc: Doc) => Doc, renderView?: () => JSX.Element, onSwitch?: () => void) => { if (!this.userDoc) return; this.userDoc.activeMobile = doc(this.userDoc); onSwitch && onSwitch(); this.renderView = renderView; } onSwitchInking = () => { InkingControl.Instance.switchTool(InkTool.Pen); MobileInterface.Instance.drawingInk = true; DocServer.Mobile.dispatchOverlayTrigger({ enableOverlay: true, width: window.innerWidth, height: window.innerHeight }); } 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) { 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 docView = DocumentManager.Instance.getDocumentView(collectionDoc); if (docView) { width = docView.nativeWidth ? docView.nativeWidth : 300; height = docView.nativeHeight ? docView.nativeHeight : 300; } } } DocServer.Mobile.dispatchOverlayTrigger({ enableOverlay: true, width: width, height: height, text: "Documents uploaded from mobile will show here", }); } 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) { const backgroundColor = () => "white"; return (
window.screen.width} PanelHeight={() => window.screen.height} renderDepth={0} focus={emptyFunction} backgroundColor={backgroundColor} parentActive={returnTrue} whenActiveChanged={emptyFunction} bringToFront={emptyFunction} ContainingCollectionView={undefined} ContainingCollectionDoc={undefined} />
); } } 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 (
this.handleClick(doc)}>{doc.title}
{doc.type}
); }); return ( <>
{this.sidebarActive ? StrCast(this._activeDoc.title) : "Menu"}
{this.createPathname()}
{this._child ? <>
{buttons}
Home
: <> {buttons} {/*
Library
*/}
Record Audio
Presentation
SettingsManager.Instance.open()}>Settings
}
{this._child ? null :
{this.renderView}
} ); } pinToPresentation = () => { // Only making button available if it is an image if (this._activeDoc.type === "image") { const isPinned = this._activeDoc && Doc.isDocPinned(this._activeDoc); return
{ if (isPinned) { DockedFrameRenderer.UnpinDoc(this._activeDoc); } else { DockedFrameRenderer.PinDoc(this._activeDoc); } }}>
; } } 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 ( //
//
//
//
//
//
//
//
//
//
//
//
// ); // } renderActiveCollection = (userDoc: Doc) => { if (this.activeContainer) { const active = Cast(this.activeContainer.data, listSpec(Doc)); if (active) { return (
HELLO!
); } } } onBack = (e: React.MouseEvent) => { this.switchCurrentView((userDoc: Doc) => this.mainDoc); InkingControl.Instance.switchTool(InkTool.None); // TODO: switch to previous tool DocServer.Mobile.dispatchOverlayTrigger({ enableOverlay: false, width: window.innerWidth, height: window.innerHeight }); // this.inkDoc = undefined; this.drawingInk = false; } shiftLeft = (e: React.MouseEvent) => { DocServer.Mobile.dispatchOverlayPositionUpdate({ dx: -10 }); e.preventDefault(); e.stopPropagation(); } shiftRight = (e: React.MouseEvent) => { DocServer.Mobile.dispatchOverlayPositionUpdate({ dx: 10 }); e.preventDefault(); e.stopPropagation(); } panelHeight = () => window.innerHeight; panelWidth = () => window.innerWidth; //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 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 }); if (uploadDoc) { DocServer.Mobile.dispatchMobileDocumentUpload({ docId: uploadDoc[Id], }); } } } e.stopPropagation(); e.preventDefault(); } addWebToCollection = async () => { let url = "https://en.wikipedia.org/wiki/Hedgehog"; if (this.mainContainer) { const data = Cast(this.mainContainer.data, listSpec(Doc)); if (data) { const webDoc = await data[0]; const urlField: FieldResult = Cast(webDoc.data, WebField); url = urlField ? urlField.url.toString() : "https://en.wikipedia.org/wiki/Hedgehog"; } } Docs.Create.WebDocument(url, { _width: 300, _height: 300, title: "Mobile Upload Web Doc" }); } clearUpload = async () => { if (this.mainContainer) { const data = Cast(this.mainContainer.data, listSpec(Doc)); if (data) { const collectionDoc = await data[1]; const children = DocListCast(collectionDoc.data); children.forEach(doc => { }); // collectionDoc[data] = new List(); } } } onDragOver = (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); } render() { // const content = this.currentView === "main" ? this.mainContent : // this.currentView === "ink" ? this.inkContent : // this.currentView === "upload" ? this.uploadContent : <>; return (
{/* {this.renderView ? this.renderView() : this.renderDefaultContent()} */} {/* */} {this.displayWorkspaces()} {this.pinToPresentation()} {/* */} {/* */} {/* */}
{this.renderDefaultContent()}
{/* */} {/* */} {/* */} {/* */}
); } } Scripting.addGlobal(function switchMobileView(doc: (userDoc: Doc) => Doc, renderView?: () => JSX.Element, onSwitch?: () => void) { return MobileInterface.Instance.switchCurrentView(doc, renderView, onSwitch); }); // WAS 2 // 1 // renderUploadContent() { // if (this.mainContainer) { // return ( //
//
// // {/* */} // {/* */} // //
// window.screen.width} // PanelHeight={() => window.screen.height} // renderDepth={0} // focus={emptyFunction} // backgroundColor={returnEmptyString} // parentActive={returnTrue} // whenActiveChanged={emptyFunction} // bringToFront={emptyFunction} // ContainingCollectionView={undefined} // ContainingCollectionDoc={undefined} /> //
// ); // } // } // 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 ( //
//
//
// //
//
// //
//
// // //
//
// // //
// ); // } // }