diff options
Diffstat (limited to 'src/mobile/MobileInterface.tsx')
-rw-r--r-- | src/mobile/MobileInterface.tsx | 1217 |
1 files changed, 565 insertions, 652 deletions
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 94394e277..02993fdcb 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -1,771 +1,684 @@ -import React = require('react'); +import * as React from "react"; import { library } from '@fortawesome/fontawesome-svg-core'; -import { faEraser, faHighlighter, faLongArrowAltLeft, faMousePointer, faPenNib, faThumbtack, faHome } from '@fortawesome/free-solid-svg-icons'; +import { + faTasks, faReply, faQuoteLeft, faHandPointLeft, faFolderOpen, faAngleDoubleLeft, faExternalLinkSquareAlt, 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, + faAlignRight, faAlignLeft +} from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, observable } from 'mobx'; +import { action, computed, observable, reaction, trace, runInAction } from 'mobx'; import { observer } from 'mobx-react'; -import * as ReactDOM from "react-dom"; -import * as rp from 'request-promise'; +import { Doc, DocListCast } from '../fields/Doc'; import { CurrentUserUtils } from '../client/util/CurrentUserUtils'; -import { FieldValue, Cast, StrCast, BoolCast } from '../fields/Types'; -import { Doc, DocListCast, Opt } from '../fields/Doc'; -import { Docs } from '../client/documents/Documents'; -import { CollectionView } from '../client/views/collections/CollectionView'; +import { emptyFunction, emptyPath, returnFalse, returnOne, returnTrue, returnZero, returnEmptyFilter } from '../Utils'; +import { Docs, DocumentOptions } from '../client/documents/Documents'; +import { Scripting } from '../client/util/Scripting'; import { DocumentView } from '../client/views/nodes/DocumentView'; -import { emptyPath, emptyFunction, returnFalse, returnOne, returnEmptyString, returnTrue, returnZero, Utils } from '../Utils'; import { Transform } from '../client/util/Transform'; -import { Scripting } from '../client/util/Scripting'; -import GestureOverlay from '../client/views/GestureOverlay'; -import { InkingControl } from '../client/views/InkingControl'; -import { InkTool } from '../fields/InkField'; import "./MobileInterface.scss"; -import "./MobileMenu.scss"; -import { DocServer } from '../client/DocServer'; -import { DocumentDecorations } from '../client/views/DocumentDecorations'; -import { PreviewCursor } from '../client/views/PreviewCursor'; -import { RadialMenu } from '../client/views/nodes/RadialMenu'; -import { Id } from '../fields/FieldSymbols'; -import { WebField, nullAudio } from "../fields/URLField"; -import { FieldResult } from "../fields/Doc"; -import { AssignAllExtensions } from '../extensions/General/Extensions'; -import { listSpec } from '../fields/Schema'; -import { DocumentManager } from '../client/util/DocumentManager'; -import RichTextMenu from '../client/views/nodes/formattedText/RichTextMenu'; -import { MainView } from '../client/views/MainView'; +import "./ImageUpload.scss"; +import "./AudioUpload.scss"; import SettingsManager from '../client/util/SettingsManager'; import { Uploader } from "./ImageUpload"; -import { createTypePredicateNodeWithModifier } from 'typescript'; -import { AudioBox } from '../client/views/nodes/AudioBox'; -import { List } from '../fields/List'; -import { ScriptField, ComputedField } from '../fields/ScriptField'; - -library.add(faLongArrowAltLeft); -library.add(faHome); +import { DockedFrameRenderer } from '../client/views/collections/CollectionDockingView'; +import { InkTool } from '../fields/InkField'; +import GestureOverlay from "../client/views/GestureOverlay"; +import { ScriptField } from "../fields/ScriptField"; +import { RadialMenu } from "../client/views/nodes/RadialMenu"; +import { UndoManager } from "../client/util/UndoManager"; +import { List } from "../fields/List"; +import { AudioUpload } from "./AudioUpload"; +import { Cast, FieldValue } from '../fields/Types'; +import RichTextMenu from "../client/views/nodes/formattedText/RichTextMenu"; +import { AudioBox } from "../client/views/nodes/AudioBox"; +import { CollectionViewType } from "../client/views/collections/CollectionView"; +import { DocumentType } from "../client/documents/DocumentTypes"; +import { CollectionFreeFormViewChrome } from "../client/views/collections/CollectionMenu"; + +library.add(faTasks, faReply, faQuoteLeft, faHandPointLeft, faFolderOpen, faAngleDoubleLeft, faExternalLinkSquareAlt, 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, + faAlignLeft, faAlignRight); @observer -export default 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; } - private get darkScheme() { return BoolCast(Cast(this.userDoc?.activeWorkspace, Doc, null)?.darkScheme); } - // @observable private currentView: "main" | "ink" | "upload" = "main"; - @observable private mainDoc: any = CurrentUserUtils.setupMobileMenu(this.userDoc); - @observable private renderView?: () => JSX.Element; - @observable private audioState: any; - - 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<Doc> = []; - private _menu: Doc = this.mainDoc; - private _open: boolean = false; - private _library: Doc = Cast(this.userDoc.myWorkspaces, Doc) as Doc; - private _ink: boolean = false; +export class MobileInterface extends React.Component { + static Instance: MobileInterface; + private _library: Doc = CurrentUserUtils.setupLibrary(Doc.UserDoc()); // to access documents in Dash Web + private _mainDoc: any = CurrentUserUtils.setupActiveMobileMenu(Doc.UserDoc()); + @observable private _sidebarActive: boolean = false; //to toggle sidebar display + @observable private _imageUploadActive: boolean = false; //to toggle image upload + @observable private _audioUploadActive: boolean = false; + @observable private _menuListView: boolean = false; //to switch between menu view (list / icon) + @observable private _ink: boolean = false; //toggle whether ink is being dispalyed + @observable private _homeMenu: boolean = true; // to determine whether currently at home menu + @observable private _child: Doc | null = null; // currently selected document + @observable private _activeDoc: Doc = this._mainDoc; // doc updated as the active mobile page is updated (initially home menu) + @observable private _homeDoc: Doc = this._mainDoc; // home menu as a document + @observable private _parents: Array<Doc> = []; // array of parent docs (for pathbar) + + @computed private get mainContainer() { return Doc.UserDoc() ? FieldValue(Cast(Doc.UserDoc().activeMobile, Doc)) : CurrentUserUtils.GuestMobile; } 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; - } - InkingControl.Instance.switchTool(InkTool.None) - MobileInterface.Instance.drawingInk = false; - InkingControl.Instance.updateSelectedColor("rgb(0, 0, 0)"); - InkingControl.Instance.switchWidth("2"); + // if the home menu is in list view -> adjust the menu toggle appropriately + this._menuListView = this._homeDoc._viewType === "stacking" ? true : false; + Doc.SetSelectedTool(InkTool.None); // ink should intially be set to none + Doc.UserDoc().activeMobile = this._homeDoc; // active mobile set to home + AudioBox.Enabled = true; + + // remove double click to avoid mobile zoom in + document.removeEventListener("dblclick", this.onReactDoubleClick); + document.addEventListener("dblclick", this.onReactDoubleClick); } @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; + componentWillUnmount = () => { + document.removeEventListener('dblclick', this.onReactDoubleClick); } - onSwitchInking = () => { - if (!this._ink) { - InkingControl.Instance.switchTool(InkTool.Pen); - MobileInterface.Instance.drawingInk = true; - this._ink = true; - - } else { - InkingControl.Instance.switchTool(InkTool.None) - MobileInterface.Instance.drawingInk = false; - this._ink = false; - } - - this.toggleSidebar(); + // Prevent zooming in when double tapping the screen + onReactDoubleClick = (e: MouseEvent) => { + e.stopPropagation(); } - 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; - } - } + // Switch the mobile view to the given doc + @action + switchCurrentView = (doc: Doc, renderView?: () => JSX.Element, onSwitch?: () => void) => { + if (!Doc.UserDoc()) return; + if (this._activeDoc === this._homeDoc) { + this._parents.push(this._activeDoc); + this._homeMenu = false; } - DocServer.Mobile.dispatchOverlayTrigger({ - enableOverlay: true, - width: width, - height: height, - text: "Documents uploaded from mobile will show here", - }); + this._activeDoc = doc; + Doc.UserDoc().activeMobile = doc; + onSwitch?.(); + + // Ensures that switching to home is not registed + UndoManager.undoStack.length = 0; + UndoManager.redoStack.length = 0; } + // For toggling the hamburger menu + @action toggleSidebar = () => { - console.log("clicked"); - let menuButton = document.getElementById("menuButton") as HTMLElement; - menuButton.classList.toggle('active'); + this._sidebarActive = !this._sidebarActive; - let sidebar = document.getElementById("sidebar") as HTMLElement; - sidebar.classList.toggle('active'); - - let header = document.getElementById("header") as HTMLElement; - - if (!sidebar.classList.contains('active')) { - header.textContent = String(this._activeDoc.title); - } else { - header.textContent = "menu"; - } - - // for updating ink button - let ink = document.getElementById("ink") as HTMLElement; - if (ink) { - if (this._ink) { - ink.textContent = "ink off"; - } else { - ink.textContent = "ink on"; - } + if (this._ink) { + this.onSwitchInking(); } } + /** + * Method called when 'Library' button is pressed on the home screen + */ + switchToLibrary = async () => { + this.switchCurrentView(this._library); + runInAction(() => this._homeMenu = false); + this.toggleSidebar(); + } + /** + * Back method for navigating through items + */ + @action back = () => { - let doc = Cast(this._parents.pop(), Doc) as Doc; - if (doc === Cast(this._menu, Doc) as Doc) { + const header = document.getElementById("header") as HTMLElement; + const doc = Cast(this._parents.pop(), Doc) as Doc; // Parent document + // Case 1: Parent document is 'workspaces' + if (doc === Cast(this._library, 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; + this.switchCurrentView(this._library); + // Case 2: Parent document is the 'home' menu (root node) + } else if (doc === Cast(this._homeDoc, Doc) as Doc) { + this._homeMenu = true; + this._parents = []; + this._child = null; + this.switchCurrentView(this._homeDoc); + // Case 3: Parent document is any document + } else if (doc) { + this._child = doc; + this.switchCurrentView(doc); + this._homeMenu = false; + header.textContent = String(doc.title); } - this._ink = false; + this._ink = false; // turns ink off } + /** + * Return 'Home", which implies returning to 'Home' menu buttons + */ + @action returnHome = () => { - this._parents = []; - this._activeDoc = this._menu; - this.switchCurrentView((userDoc: Doc) => this._menu); - this._child = null; - } - - displayWorkspaces = () => { - if (this.mainContainer) { - const backgroundColor = () => "white"; - if (this._activeDoc.title === "mobile audio") { - return ( - <div style={{ position: "relative", top: '600px', height: `calc(50% - 450px)`, width: "80%", overflow: "hidden", left: "10%", cursor: "pointer" }}> - <DocumentView - Document={this.mainContainer} - DataDoc={undefined} - LibraryPath={emptyPath} - addDocument={returnFalse} - addDocTab={returnFalse} - pinToPres={emptyFunction} - rootSelected={returnFalse} - removeDocument={undefined} - onClick={ScriptField.MakeScript('this.uploadAudio()')} - 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> - ); - } else { - return ( - <div style={{ position: "relative", top: '200px', height: `calc(100% - 250px)`, width: "80%", overflow: "hidden", left: "10%" }}> - <DocumentView - Document={this.mainContainer} - DataDoc={undefined} - LibraryPath={emptyPath} - addDocument={returnFalse} - addDocTab={returnFalse} - pinToPres={emptyFunction} - rootSelected={returnFalse} - removeDocument={undefined} - onClick={undefined} - ScreenToLocalTransform={Transform.Identity} - ContentScaling={returnOne} - NativeHeight={returnZero} - NativeWidth={returnZero} - PanelWidth={() => window.screen.width} - PanelHeight={() => window.screen.height} - renderDepth={0} - focus={emptyFunction} - backgroundColor={backgroundColor} - parentActive={returnTrue} - whenActiveChanged={emptyFunction} - bringToFront={emptyFunction} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} - /> - </div> - ); - } + if (!this._homeMenu || this._sidebarActive) { + this._homeMenu = true; + this._parents = []; + this._child = null; + this.switchCurrentView(this._homeDoc); } - } - - handleClick(doc: Doc) { - let children = DocListCast(doc.data); - if (doc.type !== "collection") { - this._parents.push(this._activeDoc); - this._activeDoc = doc; - this.switchCurrentView((userDoc: Doc) => doc); + if (this._sidebarActive) { 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; } } - createPathname = () => { - let pathname = "workspaces"; - this._parents.map((doc: Doc, index: any) => { - if (doc === this.mainDoc) { - pathname = pathname; - } else if (doc.title === "mobile audio" || doc.title === "Presentation") { - pathname = pathname; - } else if (doc.type !== "collection") { - pathname = pathname; - } else { - pathname = pathname + " > " + doc.title; - } - }); - if (this._activeDoc === this.mainDoc) { - pathname = pathname; - } else { - pathname = pathname + " > " + this._activeDoc.title; - } - - if (this._activeDoc.title === "mobile audio") { - pathname = this._activeDoc.title; - } - - if (this._activeDoc.title === "Presentation") { - pathname = this._activeDoc.title; - } - return pathname; + /** + * Return to primary Workspace in library (Workspaces Doc) + */ + @action + returnMain = () => { + this._parents = [this._homeDoc]; + this.switchCurrentView(this._library); + this._homeMenu = false; + this._child = null; } - openLibrary() { - this._activeDoc = this.mainDoc; - this.switchCurrentView((userDoc: Doc) => this.mainDoc); - this._child = this._library; + /** + * Note: window.innerWidth and window.screen.width compute different values. + * window.screen.width is the display size, however window.innerWidth is the + * display resolution which computes differently. + */ + returnWidth = () => window.innerWidth; //The windows width + returnHeight = () => (window.innerHeight - 300); //Calculating the windows height (-300 to account for topbar) + whitebackground = () => "white"; + /** + * DocumentView for graphic display of all documents + */ + @computed get displayWorkspaces() { + return !this.mainContainer ? (null) : + <div style={{ position: "relative", top: '198px', height: `calc(100% - 350px)`, width: "100%", left: "0%" }}> + <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} + PanelWidth={this.returnWidth} + PanelHeight={this.returnHeight} + NativeHeight={returnZero} + NativeWidth={returnZero} + renderDepth={0} + focus={emptyFunction} + backgroundColor={this.whitebackground} + parentActive={returnTrue} + whenActiveChanged={emptyFunction} + bringToFront={emptyFunction} + docFilters={returnEmptyFilter} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} + /> + </div>; } - renderDefaultContent = () => { - const workspaces = Cast(this.userDoc.myWorkspaces, Doc) as Doc; - let buttons = DocListCast(workspaces.data).map((doc: Doc, index: any) => { - if (doc.type !== "ink") { - 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>); + /** + * Handles the click functionality in the library panel. + * Navigates to the given doc and updates the sidebar. + * @param doc: doc for which the method is called + */ + handleClick = async (doc: Doc) => { + runInAction(() => { + if (doc.type !== "collection" && this._sidebarActive) { + this._parents.push(this._activeDoc); + this.switchCurrentView(doc); + this._homeMenu = false; + this.toggleSidebar(); + } + else { + this._parents.push(this._activeDoc); + this.switchCurrentView(doc); + this._homeMenu = false; + this._child = doc; } }); + } - if (this._child) { - buttons = DocListCast(this._child.data).map((doc: Doc, index: any) => { - if (doc.type !== "ink") { - 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>); - } - }); - } + /** + * Called when an item in the library is clicked and should + * be opened (open icon on RHS of all menu items) + * @param doc doc to be opened + */ + @action + openFromSidebar = (doc: Doc) => { + this._parents.push(this._activeDoc); + this.switchCurrentView(doc); + this._homeMenu = false; + this._child = doc; + this.toggleSidebar(); + } - if (this._activeDoc.title === "mobile audio") { - return ( - <div> - <div className="navbar"> - <div className="header" id="header"> - menu - </div> + // Renders the graphical pathbar + renderPathbar = () => { + const docPath = [...this._parents, this._activeDoc]; + const items = docPath.map((doc: Doc, index: any) => + <div className="pathbarItem" key={index}> + {index === 0 ? (null) : <FontAwesomeIcon key="icon" className="pathIcon" icon="angle-right" size="lg" />} + <div className="pathbarText" + style={{ backgroundColor: this._homeMenu || doc === this._activeDoc ? "rgb(119,17,37)" : undefined }} + onClick={() => this.handlePathClick(doc, index)}>{doc.title} + </div> + </div>); + return (<div className="pathbar"> + <div className="scrollmenu"> + {items} + </div> + {!this._parents.length ? (null) : + <div className="back" > + <FontAwesomeIcon onClick={this.back} icon={"chevron-left"} color="white" size={"2x"} /> + </div>} + <div className="hidePath" /> + </div>); + } - <div className="toggle-btn" id="menuButton" onClick={this.toggleSidebar}> - <span></span> - <span></span> - <span></span> - </div> - </div> - <div className="pathbar"> - <div className="pathname"> - {this.createPathname()} - </div> - </div> - <div className="sidebar" id="sidebar"> - <FontAwesomeIcon className="home" icon="home" onClick={this.returnHome} /> - <div className="back" onClick={this.back}> - ← - </div> - <div className="item" key="audio" onClick={() => this.uploadAudio()}> - Upload Audio - </div> - <div className="item" key="home" onClick={this.returnHome}> - Home - </div> - </div> - </div>); + // Handles when user clicks on a document in the pathbar + @action + handlePathClick = (doc: Doc, index: number) => { + if (doc === this._library) { + this._child = null; + this.switchCurrentView(doc); + this._parents.length = index; + } else if (doc === this._homeDoc) { + this.returnHome(); + } else { + this._child = doc; + this.switchCurrentView(doc); + this._parents.length = index; } + } - if (!this._child) { + // Renders the contents of the menu and sidebar + @computed get renderDefaultContent() { + if (this._homeMenu) { return ( <div> <div className="navbar"> - <div className="header" id="header">MENU</div> - + <FontAwesomeIcon className="home" icon="home" onClick={this.returnHome} /> + <div className="header" id="header">{this._homeDoc.title}</div> + <div className="cover" id="cover" onClick={e => e.stopPropagation()}></div> <div className="toggle-btn" id="menuButton" onClick={this.toggleSidebar}> <span></span> <span></span> <span></span> </div> </div> - <div className="pathbar"> - <div className="pathname"> - {this.createPathname()} - </div> - </div> - <div className="sidebar" id="sidebar"> - <FontAwesomeIcon className="home" icon="home" onClick={this.returnHome} /> - <div> - {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 className="ink" key="ink" id="ink" onClick={() => this.onSwitchInking()}> - Ink On - </div> - </div> - </div> - <div> - {this.renderView} - </div> + {this.renderPathbar()} </div> ); } - else { - return ( - <div> - <div className="navbar"> - <div className="header" id="header"> - menu - </div> - - <div className="toggle-btn" id="menuButton" onClick={this.toggleSidebar}> - <span></span> - <span></span> - <span></span> - </div> + // stores workspace documents as 'workspaces' variable + let workspaces = Cast(Doc.UserDoc().myWorkspaces, Doc) as Doc; + if (this._child) { + workspaces = this._child; + } + // returns a list of navbar buttons as 'buttons' + const buttons = DocListCast(workspaces.data).map((doc: Doc, index: any) => { + if (doc.type !== "ink") { + return ( + <div + className="item" + key={index}> + <div className="item-title" onClick={() => this.handleClick(doc)}> {doc.title} </div> + <div className="item-type" onClick={() => this.handleClick(doc)}>{doc.type}</div> + <FontAwesomeIcon onClick={() => this.handleClick(doc)} className="right" icon="angle-right" size="lg" style={{ display: `${doc.type === "collection" ? "block" : "none"}` }} /> + <FontAwesomeIcon className="open" onClick={() => this.openFromSidebar(doc)} icon="external-link-alt" size="lg" /> </div> - <div className="pathbar"> - <div className="pathname"> - {this.createPathname()} - </div> + ); + } + }); + + return ( + <div> + <div className="navbar"> + <FontAwesomeIcon className="home" icon="home" onClick={this.returnHome} /> + <div className="header" id="header">{this._sidebarActive ? "library" : this._activeDoc.title}</div> + <div className={`toggle-btn ${this._sidebarActive ? "active" : ""}`} onClick={this.toggleSidebar}> + <span></span> + <span></span> + <span></span> </div> - <div className="sidebar" id="sidebar"> - <FontAwesomeIcon className="home" icon="home" onClick={this.returnHome} /> - <div className="back" onClick={this.back}> - ← - </div> - <div> - {buttons} - </div> - <div className="item" key="ink" id="ink" onClick={() => this.onSwitchInking()}> - ink on - </div> - <div className="item" key="home" onClick={this.returnHome}> - Home - </div> + <div className={`background ${this._sidebarActive ? "active" : ""}`} onClick={this.toggleSidebar}></div> + </div> + {this.renderPathbar()} + <div className={`sidebar ${this._sidebarActive ? "active" : ""}`}> + <div className="sidebarButtons"> + {this._child ? + <> + {buttons} + <div + className="item" key="home" + onClick={this.returnMain} + style={{ opacity: 0.7 }}> + <FontAwesomeIcon className="right" icon="angle-double-left" size="lg" /> + <div className="item-type">Return to workspaces</div> + </div> + </> : + <> + {buttons} + <div + className="item" + style={{ opacity: 0.7 }} + onClick={() => this.createNewWorkspace()}> + <FontAwesomeIcon className="right" icon="plus" size="lg" /> + <div className="item-type">Create New Workspace</div> + </div> + </> + } </div> </div> - ); - } + <div className={`blanket ${this._sidebarActive ? "active" : ""}`} onClick={this.toggleSidebar}> + </div> + </div> + ); } - recordAudio = () => { - // 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; - console.log(audioDoc); - if (audioDoc) { - console.log("audioClicked: " + audioDoc.title); - this._activeDoc = audioDoc; - this.switchCurrentView((userDoc: Doc) => audioDoc); - this.toggleSidebar(); - } + /** + * Handles the 'Create New Workspace' button in the menu (taken from MainView.tsx) + */ + @action + createNewWorkspace = async (id?: string) => { + const workspaces = Cast(Doc.UserDoc().myWorkspaces, Doc) as Doc; + const workspaceCount = DocListCast(workspaces.data).length + 1; + const freeformOptions: DocumentOptions = { + x: 0, + y: 400, + title: "Collection " + workspaceCount, + }; + const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions); + const workspaceDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [Doc.UserDoc().myCatalog as Doc] }], { title: `Workspace ${workspaceCount}` }, id, "row"); + + const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`); + const toggleComic = ScriptField.MakeScript(`toggleComicMode()`); + const cloneWorkspace = ScriptField.MakeScript(`cloneWorkspace()`); + workspaceDoc.contextMenuScripts = new List<ScriptField>([toggleTheme!, toggleComic!, cloneWorkspace!]); + workspaceDoc.contextMenuLabels = new List<string>(["Toggle Theme Colors", "Toggle Comic Mode", "New Workspace Layout"]); + + Doc.AddDocToList(workspaces, "data", workspaceDoc); } - uploadAudio = () => { - const audioRightSidebar = Cast(Doc.UserDoc().rightSidebarCollection, Doc) as Doc; - const audioDoc = this._activeDoc; - const data = Cast(audioRightSidebar.data, listSpec(Doc)); - console.log(audioDoc.proto); - if (data) { - data.push(audioDoc); - } - this.recordAudio(); - } + // Button for switching between pen and ink mode + @action + onSwitchInking = () => { + const button = document.getElementById("inkButton") as HTMLElement; + button.style.backgroundColor = this._ink ? "white" : "black"; + button.style.color = this._ink ? "black" : "white"; - openDefaultPresentation = () => { - if (this._activeDoc.title !== "Presentation") { - this._parents.push(this._activeDoc); + if (!this._ink) { + Doc.SetSelectedTool(InkTool.Pen); + this._ink = true; + } else { + Doc.SetSelectedTool(InkTool.None); + this._ink = false; } + } - const presentation = Cast(Doc.UserDoc().activePresentation, Doc) as Doc; + // The static ink menu that appears at the top + @computed get inkMenu() { + return this._activeDoc._viewType !== CollectionViewType.Docking || !this._ink ? (null) : + <div className="colorSelector"> + {/* <CollectionFreeFormViewChrome /> */} + </div>; + } - if (presentation) { - console.log("presentation clicked: " + presentation.title); - this._activeDoc = presentation; - this.switchCurrentView((userDoc: Doc) => presentation); - this.toggleSidebar(); - } + // DocButton that uses UndoManager and handles the opacity change if CanUndo is true + @computed get undo() { + if (this.mainContainer && this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc && + this._activeDoc !== Doc.UserDoc()["sidebar-sharing"] && this._activeDoc.title !== "WORKSPACES") { + return ( + <div className="docButton" + style={{ backgroundColor: "black", color: "white", fontSize: "60", opacity: UndoManager.CanUndo() ? "1" : "0.4", }} + id="undoButton" + title="undo" + onClick={(e: React.MouseEvent) => { + UndoManager.Undo(); + e.stopPropagation(); + }}> + <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="undo-alt" /> + </div>); + } else return (null); } - // mobileHome = () => { - // return ( - // <div className="homeContainer"> - // <div className="uploadButton"> + // DocButton that uses UndoManager and handles the opacity change if CanRedo is true + @computed get redo() { + if (this.mainContainer && this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc && + this._activeDoc !== Doc.UserDoc()["sidebar-sharing"] && this._activeDoc.title !== "WORKSPACES") { + return ( + <div className="docButton" + style={{ backgroundColor: "black", color: "white", fontSize: "60", opacity: UndoManager.CanRedo() ? "1" : "0.4", }} + id="undoButton" + title="redo" + onClick={(e: React.MouseEvent) => { + UndoManager.Redo(); + e.stopPropagation(); + }}> + <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="redo-alt" /> + </div>); + } else return (null); + } - // </div> - // <div className="presentationButton"> + // DocButton for switching into ink mode + @computed get drawInk() { + return !this.mainContainer || this._activeDoc._viewType !== CollectionViewType.Docking ? (null) : + <div className="docButton" + id="inkButton" + title={Doc.isDocPinned(this._activeDoc) ? "Pen on" : "Pen off"} + onClick={this.onSwitchInking}> + <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="pen-nib" /> + </div>; + } - // </div> - // <div className="recordAudioButton"> + // DocButton: Button that appears on the bottom of the screen to initiate image upload + @computed get uploadImageButton() { + if (this._activeDoc.type === DocumentType.COL && this._activeDoc !== this._homeDoc && this._activeDoc._viewType !== CollectionViewType.Docking && this._activeDoc.title !== "WORKSPACES") { + return <div className="docButton" + id="imageButton" + title={Doc.isDocPinned(this._activeDoc) ? "Pen on" : "Pen off"} + onClick={this.toggleUpload}> + <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="upload" /> + </div>; + } else return (null); + } - // </div> - // <div className="inkButton"> + // DocButton to download images on the mobile + @computed get downloadDocument() { + if (this._activeDoc.type === "image" || this._activeDoc.type === "pdf" || this._activeDoc.type === "video") { + return <div className="docButton" + title={"Download Image"} + style={{ backgroundColor: "white", color: "black" }} + onClick={e => window.open(this._activeDoc["data-path"]?.toString())}> {/* daa-path holds the url */} + <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="download" /> + </div>; + } else return (null); + } - // </div> - // <div className="settingsButton"> + // DocButton for pinning images to presentation + @computed get pinToPresentation() { + // Only making button available if it is an image + if (!(this._activeDoc.type === "collection" || this._activeDoc.type === "presentation")) { + const isPinned = this._activeDoc && Doc.isDocPinned(this._activeDoc); + return <div className="docButton" + title={Doc.isDocPinned(this._activeDoc) ? "Unpin from presentation" : "Pin to presentation"} + style={{ backgroundColor: isPinned ? "black" : "white", color: isPinned ? "white" : "black" }} + onClick={e => DockedFrameRenderer.PinDoc(this._activeDoc, isPinned)}> + <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin" /> + </div>; + } else return (null); + } - // </div> - // </div> - // ); - // } + // Buttons for switching the menu between large and small icons + @computed get switchMenuView() { + return this._activeDoc.title !== this._homeDoc.title ? (null) : + <div className="homeSwitch"> + <div className={`list ${!this._menuListView ? "active" : ""}`} onClick={this.changeToIconView}> + <FontAwesomeIcon size="sm" icon="th-large" /> + </div> + <div className={`list ${this._menuListView ? "active" : ""}`} onClick={this.changeToListView}> + <FontAwesomeIcon size="sm" icon="bars" /> + </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> - ); - } + // Logic for switching the menu into the icons + @action + changeToIconView = () => { + if (this._homeDoc._viewType = "stacking") { + this._menuListView = false; + this._homeDoc._viewType = "masonry"; + this._homeDoc.columnWidth = 300; + this._homeDoc._columnWidth = 300; + const menuButtons = DocListCast(this._homeDoc.data); + menuButtons.map(doc => { + const buttonData = DocListCast(doc.data); + buttonData[1]._nativeWidth = 0.1; + buttonData[1]._width = 0.1; + buttonData[1]._dimMagnitude = 0; + buttonData[1]._opacity = 0; + doc._nativeWidth = 400; + }); } } - onBack = (e: React.MouseEvent) => { - this.switchCurrentView((userDoc: Doc) => this.mainDoc); - InkingControl.Instance.switchTool(InkTool.None); // TODO: switch to previous tool + // Logic for switching the menu into the stacking view + @action + changeToListView = () => { + if (this._homeDoc._viewType = "masonry") { + this._homeDoc._viewType = "stacking"; + this._menuListView = true; + const menuButtons = DocListCast(this._homeDoc.data); + menuButtons.map(doc => { + const buttonData = DocListCast(doc.data); + buttonData[1]._nativeWidth = 450; + buttonData[1]._dimMagnitude = 2; + buttonData[1]._opacity = 1; + doc._nativeWidth = 900; + }); + } + } - DocServer.Mobile.dispatchOverlayTrigger({ - enableOverlay: false, - width: window.innerWidth, - height: window.innerHeight - }); + // For setting up the presentation document for the home menu + @action + setupDefaultPresentation = () => { + const presentation = Cast(Doc.UserDoc().activePresentation, Doc) as Doc; - // this.inkDoc = undefined; - this.drawingInk = false; + if (presentation) { + this.switchCurrentView(presentation); + this._homeMenu = false; + } } - shiftLeft = (e: React.MouseEvent) => { - DocServer.Mobile.dispatchOverlayPositionUpdate({ - dx: -10 - }); - e.preventDefault(); - e.stopPropagation(); - } + // For toggling image upload pop up + @action + toggleUpload = () => this._imageUploadActive = !this._imageUploadActive - shiftRight = (e: React.MouseEvent) => { - DocServer.Mobile.dispatchOverlayPositionUpdate({ - dx: 10 - }); - e.preventDefault(); - e.stopPropagation(); + // For toggling audio record and dictate pop up + @action + toggleAudio = () => this._audioUploadActive = !this._audioUploadActive + + // Button for toggling the upload pop up in a collection + @action + toggleUploadInCollection = () => { + const button = document.getElementById("imageButton") as HTMLElement; + button.style.backgroundColor = this._imageUploadActive ? "white" : "black"; + button.style.color = this._imageUploadActive ? "black" : "white"; + + this._imageUploadActive = !this._imageUploadActive; } - 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(); + // For closing the image upload pop up + @action + closeUpload = () => { + this._imageUploadActive = false; } - 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<WebField> = Cast(webDoc.data, WebField); - url = urlField ? urlField.url.toString() : "https://en.wikipedia.org/wiki/Hedgehog"; + // Returns the image upload pop up + @computed get uploadImage() { + const doc = !this._homeMenu ? this._activeDoc : Cast(Doc.UserDoc()["sidebar-sharing"], Doc) as Doc; + return <Uploader Document={doc} />; + } - } - } - 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<Doc>(); - } - } + // Radial menu can only be used if it is a colleciton and it is not a homeDoc + // (and cannot be used on Workspace to avoid pin to presentation opening on right) + @computed get displayRadialMenu() { + return this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc && + this._activeDoc._viewType !== CollectionViewType.Docking ? <RadialMenu /> : (null); } + onDragOver = (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); } + /** + * MENU BUTTON + * Switch view from mobile menu to access the mobile uploads + * Global function name: openMobileUploads() + */ + @action + switchToMobileUploads = () => { + const mobileUpload = Cast(Doc.UserDoc()["sidebar-sharing"], Doc) as Doc; + this.switchCurrentView(mobileUpload); + this._homeMenu = false; + } render() { - // const content = this.currentView === "main" ? this.mainContent : - // this.currentView === "ink" ? this.inkContent : - // this.currentView === "upload" ? this.uploadContent : <></>;onDragOver={this.onDragOver} return ( - <div className="mobileInterface-container" > - {/* <DocumentDecorations /> - <GestureOverlay> - {this.renderView ? this.renderView() : this.renderDefaultContent()} - </GestureOverlay> */} - {/* <GestureOverlay> */} + <div className="mobileInterface-container" onDragOver={this.onDragOver}> <SettingsManager /> + <div className={`image-upload ${this._imageUploadActive ? "active" : ""}`}> + {this.uploadImage} + </div> + <div className={`audio-upload ${this._audioUploadActive ? "active" : ""}`}> + <AudioUpload /> + </div> + {this.switchMenuView} + {this.inkMenu} <GestureOverlay> - {this.displayWorkspaces()} - {this.renderDefaultContent()} + <div style={{ display: "none" }}><RichTextMenu key="rich" /></div> + <div className="docButtonContainer"> + {this.pinToPresentation} + {this.downloadDocument} + {this.undo} + {this.redo} + {this.drawInk} + {this.uploadImageButton} + </div> + {this.displayWorkspaces} + {this.renderDefaultContent} </GestureOverlay> - - {/* </GestureOverlay> */} - {/* <DictationOverlay /> - <SharingManager /> - <GoogleAuthenticationManager /> */} - {/* <DocumentDecorations /> */} - {/* <PreviewCursor /> */} - {/* <ContextMenu /> */} - <RadialMenu /> - {/* <RichTextMenu /> */} - {/* <PDFMenu /> - <MarqueeOptionsMenu /> - <OverlayView /> */} + {this.displayRadialMenu} </div> ); } } -Scripting.addGlobal(function switchMobileView(doc: (userDoc: Doc) => Doc, renderView?: () => JSX.Element, onSwitch?: () => void) { return MobileInterface.Instance.switchCurrentView(doc, renderView, onSwitch); }); -// WAS 2 -AssignAllExtensions(); - -(async () => { - const info = await CurrentUserUtils.loadCurrentUser(); - DocServer.init(window.location.protocol, window.location.hostname, 4321, info.email + " (mobile)"); - await Docs.Prototypes.initialize(); - if (info.id !== "__guest__") { - // a guest will not have an id registered - await CurrentUserUtils.loadUserDocument(info); - } - document.getElementById('root')!.addEventListener('wheel', event => { - if (event.ctrlKey) { - event.preventDefault(); - } - }, true); - ReactDOM.render(<MobileInterface />, document.getElementById('root')); -})(); - - -// 1 -// renderUploadContent() { -// if (this.mainContainer) { -// return ( -// <div className="mobileInterface" onDragOver={this.onDragOver}> -// <div className="mobileInterface-inkInterfaceButtons"> -// <button className="mobileInterface-button cancel" onClick={this.onBack} title="Back">BACK</button> -// {/* <button className="mobileInterface-button" onClick={this.clearUpload} title="Clear Upload">CLEAR</button> */} -// {/* <button className="mobileInterface-button" onClick={this.addWeb} title="Add Web Doc to Upload Collection"></button> */} -// <button className="mobileInterface-button" onClick={this.upload} title="Upload">UPLOAD</button> -// </div> -// <DocumentView -// Document={this.mainContainer} -// DataDoc={undefined} -// LibraryPath={emptyPath} -// addDocument={returnFalse} -// addDocTab={returnFalse} -// pinToPres={emptyFunction} -// rootSelected={returnFalse} -// removeDocument={undefined} -// onClick={undefined} -// ScreenToLocalTransform={Transform.Identity} -// ContentScaling={returnOne} -// NativeHeight={returnZero} -// NativeWidth={returnZero} -// PanelWidth={() => window.screen.width} -// PanelHeight={() => window.screen.height} -// renderDepth={0} -// focus={emptyFunction} -// backgroundColor={returnEmptyString} -// parentActive={returnTrue} -// whenActiveChanged={emptyFunction} -// bringToFront={emptyFunction} -// ContainingCollectionView={undefined} -// ContainingCollectionDoc={undefined} /> -// </div> -// ); -// } -// } - -// 2 -// Scripting.addGlobal(function onSwitchMobileInking() { return MobileInterface.Instance.onSwitchInking(); }); -// Scripting.addGlobal(function renderMobileInking() { return MobileInterface.Instance.renderInkingContent(); }); -// Scripting.addGlobal(function onSwitchMobileUpload() { return MobileInterface.Instance.onSwitchUpload(); }); -// Scripting.addGlobal(function renderMobileUpload() { return MobileInterface.Instance.renderUploadContent(); }); - // Scripting.addGlobal(function addWebToMobileUpload() { return MobileInterface.Instance.addWebToCollection(); }); - - -// 3 - // renderInkingContent = () => { - // console.log("rendering inking content"); - // // TODO: support panning and zooming - // // TODO: handle moving of ink strokes - // if (this.mainContainer) { - // return ( - // <div className="mobileInterface"> - // <div className="mobileInterface-inkInterfaceButtons"> - // <div className="navButtons"> - // <button className="mobileInterface-button cancel" onClick={this.onBack} title="Cancel drawing">BACK</button> - // </div> - // <div className="inkSettingButtons"> - // <button className="mobileInterface-button cancel" onClick={this.onBack} title="Cancel drawing"><FontAwesomeIcon icon="long-arrow-alt-left" /></button> - // </div> - // <div className="navButtons"> - // <button className="mobileInterface-button" onClick={this.shiftLeft} title="Shift left">left</button> - // <button className="mobileInterface-button" onClick={this.shiftRight} title="Shift right">right</button> - // </div> - // </div> - // <CollectionView - // Document={this.mainContainer} - // DataDoc={undefined} - // LibraryPath={emptyPath} - // fieldKey={""} - // dropAction={"alias"} - // bringToFront={emptyFunction} - // addDocTab={returnFalse} - // pinToPres={emptyFunction} - // PanelWidth={this.panelWidth} - // PanelHeight={this.panelHeight} - // NativeHeight={returnZero} - // NativeWidth={returnZero} - // focus={emptyFunction} - // isSelected={returnFalse} - // select={emptyFunction} - // active={returnFalse} - // ContentScaling={returnOne} - // whenActiveChanged={returnFalse} - // ScreenToLocalTransform={Transform.Identity} - // renderDepth={0} - // ContainingCollectionView={undefined} - // ContainingCollectionDoc={undefined} - // rootSelected={returnTrue}> - // </CollectionView> - // </div> - // ); - // } - // }
\ No newline at end of file +//Global functions for mobile menu +Scripting.addGlobal(function switchToMobileLibrary() { return MobileInterface.Instance.switchToLibrary(); }, + "opens the library to navigate through workspaces on Dash Mobile"); +Scripting.addGlobal(function openMobileUploads() { return MobileInterface.Instance.toggleUpload(); }, + "opens the upload files menu for Dash Mobile"); +Scripting.addGlobal(function switchToMobileUploadCollection() { return MobileInterface.Instance.switchToMobileUploads(); }, + "opens the mobile uploads collection on Dash Mobile"); +Scripting.addGlobal(function openMobileAudio() { return MobileInterface.Instance.toggleAudio(); }, + "opens the record and dictate menu on Dash Mobile"); +Scripting.addGlobal(function switchToMobilePresentation() { return MobileInterface.Instance.setupDefaultPresentation(); }, + "opens the presentation on Dash Mobile"); +Scripting.addGlobal(function openMobileSettings() { return SettingsManager.Instance.open(); }, + "opens settings on Dash Mobile"); + +// Other global functions for mobile +Scripting.addGlobal(function switchMobileView(doc: Doc, renderView?: () => JSX.Element, onSwitch?: () => void) { return MobileInterface.Instance.switchCurrentView(doc, renderView, onSwitch); }, + "changes the active document displayed on the Dash Mobile", "(doc: any)");
\ No newline at end of file |