import * as React from "react"; import { library } from '@fortawesome/fontawesome-svg-core'; import { faTasks, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus, faTerminal, faToggleOn, faFile as fileSolid, faExternalLinkAlt, faLocationArrow, faSearch, faFileDownload, faStop, faCalculator, faWindowMaximize, faAddressCard, faQuestionCircle, faArrowLeft, faArrowRight, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt, faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter, faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faThumbtack, faTree, faTv, faBook, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faHome, faLongArrowAltLeft, faBars, faTh, faChevronLeft } 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 { Doc, DocListCast, FieldResult } from '../fields/Doc'; import { Id } from '../fields/FieldSymbols'; import { FieldValue, Cast, StrCast } from '../fields/Types'; import { CurrentUserUtils } from '../client/util/CurrentUserUtils'; import { emptyPath, emptyFunction, returnFalse, returnOne, returnTrue, returnZero, Utils } from '../Utils'; import { DocServer } from '../client/DocServer'; import { Docs } from '../client/documents/Documents'; import { Scripting } from '../client/util/Scripting'; import { DocumentView } from '../client/views/nodes/DocumentView'; import { Transform } from '../client/util/Transform'; // import { InkingControl } from '../client/views/InkingControl'; import "./MobileInterface.scss"; import "./MobileMenu.scss"; import "./MobileHome.scss"; import "./ImageUpload.scss"; import { DocumentManager } from '../client/util/DocumentManager'; import SettingsManager from '../client/util/SettingsManager'; import { Uploader } from "./ImageUpload"; import { DockedFrameRenderer } from '../client/views/collections/CollectionDockingView'; import { InkTool } from '../fields/InkField'; import { listSpec } from '../fields/Schema'; import { nullAudio, WebField } from '../fields/URLField'; import GestureOverlay from "../client/views/GestureOverlay"; import { SelectionManager } from "../client/util/SelectionManager"; import { SketchPicker } from "react-color"; import { ScriptField } from "../fields/ScriptField"; import InkOptionsMenu from "../client/views/collections/collectionFreeForm/InkOptionsMenu"; import { RadialMenu } from "../client/views/nodes/RadialMenu"; library.add(faTasks, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus, faTerminal, faToggleOn, fileSolid, faExternalLinkAlt, faLocationArrow, faSearch, faFileDownload, faStop, faCalculator, faWindowMaximize, faAddressCard, faQuestionCircle, faArrowLeft, faArrowRight, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt, faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter, faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faThumbtack, faTree, faTv, faUndoAlt, faBook, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faHome, faLongArrowAltLeft, faBars, faTh, faChevronLeft); @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; } @observable private mainDoc: any = CurrentUserUtils.setupActiveMobile(this.userDoc); @observable private renderView?: () => JSX.Element; @observable private audioState: any; @observable private activeToolbar: boolean = false; @observable private sidebarActive: boolean = false; @observable private imageUploadActive: boolean = false; @observable private menuListView: boolean = false; public _activeDoc: Doc = this.mainDoc; public _homeDoc: Doc = this.mainDoc; private _homeMenu: boolean = true; // private inkDoc?: Doc; public drawingInk: boolean = false; // private _uploadDoc: Doc = this.userDoc; private _child: Doc | null = null; private _parents: Array = []; private _library: Doc = CurrentUserUtils.setupLibrary(this.userDoc); private _open: boolean = false; // private _library: Doc = Cast(this.userDoc.myWorkspaces, Doc) as Doc; @observable private _ink: boolean = false; constructor(props: Readonly<{}>) { super(props); MobileInterface.Instance = this; } @action componentDidMount = () => { Doc.UserDoc().activeMobile = this._homeDoc; this._homeDoc._viewType === "stacking" ? this.menuListView = true : this.menuListView = false; Doc.SetSelectedTool(InkTool.None); this.switchCurrentView((userDoc: Doc) => this._homeDoc); document.removeEventListener("dblclick", this.onReactDoubleClick); document.addEventListener("dblclick", this.onReactDoubleClick); } onReactDoubleClick = (e: MouseEvent) => { console.log("tapped"); e.stopPropagation(); } @action switchCurrentView = (doc: (userDoc: Doc) => Doc, renderView?: () => JSX.Element, onSwitch?: () => void) => { if (!this.userDoc) return; Doc.UserDoc().activeMobile = doc(this.userDoc); onSwitch && onSwitch(); this.renderView = renderView; } 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", }); } @action toggleSidebar = () => this.sidebarActive = !this.sidebarActive /** * Method called when 'Library' button is pressed */ switchToLibrary = () => { this._parents.push(this._activeDoc); this.switchCurrentView((userDoc: Doc) => this._library); this._activeDoc = this._library; this._homeMenu = false; this.sidebarActive = true; } /** * Back method for navigating within library */ back = () => { let header = document.getElementById("header") as HTMLElement; let doc = Cast(this._parents.pop(), Doc) as Doc; if (doc === Cast(this._library, Doc) as Doc) { this._child = null; this.userDoc.activeMobile = this._library; } else if (doc === Cast(this._homeDoc, Doc) as Doc) { this._homeMenu = true; this._parents = []; this._activeDoc = this._homeDoc; this._child = null; this.switchCurrentView((userDoc: Doc) => this._homeDoc); } else { if (doc) { this._child = doc; this.switchCurrentView((userDoc: Doc) => doc); this._homeMenu = false; header.textContent = String(doc.title); } } if (doc) { this._activeDoc = doc; } this._ink = false; } /** * Return 'Home", which implies returning to 'Home' buttons */ returnHome = () => { if (this._homeMenu === false || this.sidebarActive === true) { this._homeMenu = true; this._parents = []; this._activeDoc = this._homeDoc; this._child = null; this.switchCurrentView((userDoc: Doc) => this._homeDoc); } if (this.sidebarActive) { this.toggleSidebar(); } } /** * Return to primary Workspace in library (Workspaces Doc) */ returnMain = () => { console.log("home"); this._parents = [this._homeDoc]; // this.toggleSidebar(); this._activeDoc = this._library; this.switchCurrentView((userDoc: Doc) => this._library); this._homeMenu = false; this._child = null; } // @computed get onChildClickHandler() { return ScriptCast(Doc.UserDoc.onClick); } /** * DocumentView for graphic display of all documents */ displayWorkspaces = () => { if (this.mainContainer) { const backgroundColor = () => "white"; return (
); } } returnWidth = () => window.innerWidth; //The windows width returnHeight = () => (window.innerHeight - 300); //Calculating the windows height (-300 to account for topbar) /** * Handles the click functionality in the library panel * @param doc: doc for which the method is called */ handleClick = async (doc: Doc) => { let children = DocListCast(doc.data); if (doc.type !== "collection") { this._parents.push(this._activeDoc); this._activeDoc = doc; this.switchCurrentView((userDoc: Doc) => doc); this._homeMenu = false; 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._homeMenu = false; this._child = doc; } // let sidebar = document.getElementById("sidebar") as HTMLElement; // sidebar.classList.toggle('active'); } /** * Handles creation of array which is then rendered in renderPathbar() */ createPathname = () => { // let pathname = 'workspaces'; // let titleArray = []; let docArray = []; this._parents.map((doc: Doc, index: any) => { docArray.push(doc); }); docArray.push(this._activeDoc); return docArray; } // Renders the graphical pathbar renderPathbar = () => { // if (this._homeMenu == false) { let docArray = this.createPathname(); let items = docArray.map((doc: Doc, index: any) => { if (index === 0) { return ( <> {this._homeMenu ?
this.handlePathClick(doc, index)}>{doc.title}
:
this.handlePathClick(doc, index)}>{doc.title}
} ); } else if (doc === this._activeDoc) { return (
this.handlePathClick(doc, index)}>{doc.title}
); } else { return (
this.handlePathClick(doc, index)}>{doc.title}
); } }); if (this._parents.length !== 0) { return (
{items}
); } else { return (
{items}
); } } // Handles when user clicks on document in the pathbar handlePathClick = (doc: Doc, index: number) => { if (doc === this._library) { this._activeDoc = doc; this._child = null; this.switchCurrentView((userDoc: Doc) => doc); this._parents.length = index; } else if (doc === this._homeDoc) { this.returnHome(); } else { this._activeDoc = doc; this._child = doc; this.switchCurrentView((userDoc: Doc) => doc); this._parents.length = index; } } renderDefaultContent = () => { if (this._homeMenu === true) { return (
this.stop(e)}>
{this.renderPathbar()}
); } let workspaces = Cast(this.userDoc.myWorkspaces, Doc) as Doc; if (this._child) { workspaces = this._child; } let buttons = DocListCast(workspaces.data).map((doc: Doc, index: any) => { if (doc.type !== "ink") { return (
this.handleClick(doc)}>{doc.title}
{doc.type}
); } }); return (
{this.renderPathbar()}
{this._child ? <> {buttons}
Return to library
: <> {buttons}
ScriptField.MakeScript("createNewWorkspace()")}>Create New Workspace
}
); } stop = (e: React.MouseEvent) => { e.stopPropagation(); } uploadAudioButton = () => { if (this._activeDoc.type === "audio") { return
; } } @action toggleSelector = () => this.activeToolbar = !this.activeToolbar colorTool = () => { if (this._activeDoc._viewType === "docking") { // const color = InkingControl.Instance.selectedColor; const color = "lightpink"; const selDoc = SelectionManager.SelectedDocuments()?.[0]?.rootDoc; return (
{/* */}
{/* ) => InkingControl.Instance.switchWidth(e.target.value)} /> */}
); } } @action onSwitchInking = () => { const button = document.getElementById("inkButton") as HTMLElement; // const color = InkingControl.Instance.selectedColor; const color = "lightpink"; button.style.backgroundColor = this._ink ? "white" : "black"; button.style.color = this._ink ? "black" : "white"; if (!this._ink) { console.log("INK IS ACTIVE"); // InkingControl.Instance.switchTool(InkTool.Pen); Doc.SetSelectedTool(InkTool.Pen); //InkOptionsMenu.Instance.jumpTo(300, 300); this._ink = true; } else { console.log("INK IS INACTIVE"); // InkingControl.Instance.switchTool(InkTool.None); Doc.SetSelectedTool(InkTool.None); //InkOptionsMenu.Instance.fadeOut(true); this._ink = false; } } inkMenu = () => { if (this._activeDoc._viewType === "docking") { if (this._ink) { console.log("here"); return
} } } drawInk = () => { if (this._activeDoc._viewType === "docking") { const inkIsOn = this._ink; return ( <>
{/*
*/} : ); } } downloadDocument = () => { if (this._activeDoc.type === "image") { const url = this._activeDoc["data-path"]?.toString(); return
{ window.open(url); console.log(url); }}>
; } } recordAudio = async () => { // upload to server with known URL if (this._activeDoc.title !== "mobile audio") { this._parents.push(this._activeDoc); } const audioDoc = Cast(Docs.Create.AudioDocument(nullAudio, { _width: 200, _height: 100, title: "mobile audio" }), Doc) as Doc; if (audioDoc) { this._activeDoc = audioDoc; this.switchCurrentView((userDoc: Doc) => audioDoc); this._homeMenu = false; // this.toggleSidebar(); } // const audioRightSidebar = Cast(Doc.UserDoc().rightSidebarCollection, Doc) as Doc; // this.audioState = await audioDoc.getProto; // if (this.audioState) { // console.log(this.audioState); // const data = Cast(audioRightSidebar.data, listSpec(Doc)); // if (data) { // data.push(audioDoc); // } // } } uploadAudio = () => { const audioRightSidebar = Cast(Doc.UserDoc().rightSidebarCollection, Doc) as Doc; const audioDoc = this._activeDoc; const data = Cast(audioRightSidebar.data, listSpec(Doc)); if (data) { data.push(audioDoc); } // this.recordAudio(); } panelHeight = () => window.innerHeight; panelWidth = () => window.innerWidth; //WAS 3 //WAS 1 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); } }}>
; } } switchMenuView = () => { if (this._activeDoc.title === this._homeDoc.title) { return (
); } } @action changeToIconView = () => { if (this._homeDoc._viewType = "stacking") { this.menuListView = false; this._homeDoc._viewType = "masonry"; this._homeDoc.columnWidth = 300; const menuButtons = DocListCast(this._homeDoc.data); console.log('hello'); menuButtons.map((doc: Doc, index: any) => { console.log(index); const buttonData = DocListCast(doc.data); buttonData[1]._nativeWidth = 0.1; buttonData[1]._width = 0.1; buttonData[1]._dimMagnitude = 0; buttonData[1]._opacity = 0; console.log(buttonData); console.log(doc._nativeWidth); doc._nativeWidth = 400; console.log(doc._nativeWidth); }); } } @action changeToListView = () => { if (this._homeDoc._viewType = "masonry") { this._homeDoc._viewType = "stacking"; this.menuListView = true; const menuButtons = DocListCast(this._homeDoc.data); console.log('hello'); menuButtons.map((doc: Doc, index: any) => { const buttonData = DocListCast(doc.data); buttonData[1]._nativeWidth = 450; buttonData[1]._dimMagnitude = 2; buttonData[1]._opacity = 1; console.log(doc._nativeWidth); doc._nativeWidth = 900; console.log(doc._nativeWidth); }); } } setupDefaultPresentation = () => { if (this._activeDoc.title !== "Presentation") { 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._homeMenu = false; // this.toggleSidebar(); } } 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 : <>;onDragOver={this.onDragOver} return (
{/* {this.renderView ? this.renderView() : this.renderDefaultContent()} */} {/* */} {/* {this.menuOptions()} */} {/* {this.displayHome()} */}
{this.uploadImage()}
{this.switchMenuView()}
{this.pinToPresentation()} {this.downloadDocument()} {this.drawInk()} {this.uploadAudioButton()} {/* {this.colorTool()} */}
{this.inkMenu()} {this.displayWorkspaces()} {this.renderDefaultContent()} {/*
*/} {/* */} {/* */} {/*
{this.renderDefaultContent()}
*/} {/* */} {/* */} {/* */} {/* */}
); } @action toggleUpload = () => this.imageUploadActive = !this.imageUploadActive @action closeUpload = () => { this.imageUploadActive = false; } uploadImage = () => { if (this.imageUploadActive) { console.log("active"); } else if (!this.imageUploadActive) { } return (
); } } Scripting.addGlobal(function switchMobileView(doc: (userDoc: Doc) => Doc, renderView?: () => JSX.Element, onSwitch?: () => void) { return MobileInterface.Instance.switchCurrentView(doc, renderView, onSwitch); }); Scripting.addGlobal(function openMobilePresentation() { return MobileInterface.Instance.setupDefaultPresentation(); }); Scripting.addGlobal(function toggleMobileSidebar() { return MobileInterface.Instance.toggleSidebar(); }); Scripting.addGlobal(function openMobileAudio() { return MobileInterface.Instance.recordAudio(); }); Scripting.addGlobal(function openMobileSettings() { return SettingsManager.Instance.open(); }); Scripting.addGlobal(function switchToLibrary() { return MobileInterface.Instance.switchToLibrary(); }); Scripting.addGlobal(function uploadImageMobile() { return MobileInterface.Instance.toggleUpload(); }); // 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} /> //
// ); // } // } // 3 // renderInkingContent = () => { // console.log("rendering inking content"); // // TODO: support panning and zooming // // TODO: handle moving of ink strokes // if (this.mainContainer) { // return ( //
//
//
// //
//
// //
//
// // //
//
// // //
// ); // } // }