diff options
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 54 | ||||
-rw-r--r-- | src/client/util/SettingsManager.scss | 10 | ||||
-rw-r--r-- | src/client/views/AntimodeMenu.scss | 16 | ||||
-rw-r--r-- | src/client/views/nodes/AudioBox.scss | 8 | ||||
-rw-r--r-- | src/client/views/nodes/PDFBox.scss | 188 | ||||
-rw-r--r-- | src/client/views/nodes/PresBox.scss | 47 | ||||
-rw-r--r-- | src/client/views/presentationview/PresElementBox.scss | 78 | ||||
-rw-r--r-- | src/mobile/AudioUpload.tsx | 84 | ||||
-rw-r--r-- | src/mobile/ImageUpload.tsx | 61 | ||||
-rw-r--r-- | src/mobile/MobileHome.scss | 101 | ||||
-rw-r--r-- | src/mobile/MobileInterface.scss | 448 | ||||
-rw-r--r-- | src/mobile/MobileInterface.tsx | 116 | ||||
-rw-r--r-- | src/mobile/MobileMenu.scss | 475 |
13 files changed, 665 insertions, 1021 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index e402718bf..8e53c7a3c 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -55,9 +55,20 @@ export class CurrentUserUtils { removeDropProperties: new List<string>(["dropAction"]), title: "query view", icon: "question-circle" }); } - + // Prototype for mobile button (not sure if 'Advanced Item Prototypes' is ideal location) if (doc["template-mobile-button"] === undefined) { - const queryTemplate = this.mobileButton({ title: "NEW MOBILE BUTTON", onClick: undefined, _backgroundColor: "lightgrey" }, [this.ficon({ ignoreClick: true, icon: "mobile", backgroundColor: "rgba(0,0,0,0)" }), this.mobileTextContainer({}, [this.mobileButtonText({}, "NEW MOBILE BUTTON"), this.mobileButtonInfo({}, "You can customize this button and make it your own.")])]); + const queryTemplate = this.mobileButton({ + title: "NEW MOBILE BUTTON", + onClick: undefined, + _backgroundColor: "lightgrey" + }, + [this.ficon({ + ignoreClick: true, + icon: "mobile", + backgroundColor: "rgba(0,0,0,0)" + }), + this.mobileTextContainer({}, + [this.mobileButtonText({}, "NEW MOBILE BUTTON"), this.mobileButtonInfo({}, "You can customize this button and make it your own.")])]); doc["template-mobile-button"] = CurrentUserUtils.ficon({ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: new PrefetchProxy(queryTemplate) as any as Doc, @@ -457,6 +468,7 @@ export class CurrentUserUtils { return doc.myItemCreators as Doc; } + // Sets up mobile menu if it is undefined creates a new one, otherwise returns existing menu static setupActiveMobileMenu(doc: Doc) { if (doc.activeMobileMenu === undefined) { console.log("undefined"); @@ -465,6 +477,7 @@ export class CurrentUserUtils { return doc.activeMobileMenu as Doc; } + // Sets up mobileMenu stacking document static setupMobileMenu() { const menu = new PrefetchProxy(Docs.Create.StackingDocument(this.setupMobileButtons(), { _width: 980, ignoreClick: true, lockedPosition: false, _chromeStatus: "disabled", title: "home", _yMargin: 100 @@ -472,15 +485,17 @@ export class CurrentUserUtils { return menu; } + // SEts up mobile buttons for inside mobile menu static setupMobileButtons(doc?: Doc, buttons?: string[]) { const docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, ischecked?: string, activePen?: Doc, backgroundColor?: string, info: string, dragFactory?: Doc }[] = [ { title: "WORKSPACES", icon: "bars", click: 'switchToMobileLibrary()', backgroundColor: "lightgrey", info: "Access your Workspaces from your mobile, and navigate through all of your documents. " }, - { title: "UPLOAD", icon: "upload", click: 'uploadImageMobile()', backgroundColor: "lightgrey", info: "Upload files from your mobile device so they can be accessed on Dash Web." }, - { title: "MOBILE UPLOAD", icon: "mobile", click: 'switchToMobileUploads()', backgroundColor: "lightgrey", info: "Access the collection of your mobile uploads." }, + { title: "UPLOAD", icon: "upload", click: 'openMobileUploads()', backgroundColor: "lightgrey", info: "Upload files from your mobile device so they can be accessed on Dash Web." }, + { title: "MOBILE UPLOAD", icon: "mobile", click: 'switchToMobileUploadCollection()', backgroundColor: "lightgrey", info: "Access the collection of your mobile uploads." }, { title: "RECORD", icon: "microphone", click: 'openMobileAudio()', backgroundColor: "lightgrey", info: "Use your phone to record, dictate and then upload audio onto Dash Web." }, - { title: "PRESENTATION", icon: "desktop", click: 'openMobilePresentation()', backgroundColor: "lightgrey", info: "Use your phone as a remote for you presentation." }, + { title: "PRESENTATION", icon: "desktop", click: 'switchToMobilePresentation()', backgroundColor: "lightgrey", info: "Use your phone as a remote for you presentation." }, { title: "SETTINGS", icon: "cog", click: 'openMobileSettings()', backgroundColor: "lightgrey", info: "Change your password, log out, or manage your account security." } ]; + // returns a list of mobile buttons return docProtoData.filter(d => !buttons || !buttons.includes(d.title)).map(data => this.mobileButton({ title: data.title, @@ -492,24 +507,27 @@ export class CurrentUserUtils { ); } + // sets up the main document for the mobile button static mobileButton = (opts: DocumentOptions, docs: Doc[]) => Docs.Create.MulticolumnDocument(docs, { ...opts, dropAction: undefined, removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 900, _nativeHeight: 250, _width: 900, _height: 250, _yMargin: 15, borderRounding: "5px", boxShadow: "0 0", _chromeStatus: "disabled" }) as any as Doc + // sets up the text container for the information contained within the mobile button static mobileTextContainer = (opts: DocumentOptions, docs: Doc[]) => Docs.Create.MultirowDocument(docs, { ...opts, dropAction: undefined, removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 450, _nativeHeight: 250, _width: 450, _height: 250, _yMargin: 25, backgroundColor: "rgba(0,0,0,0)", borderRounding: "0", boxShadow: "0 0", _chromeStatus: "disabled", ignoreClick: true }) as any as Doc - + // Sets up the title of the button static mobileButtonText = (opts: DocumentOptions, buttonTitle: string) => Docs.Create.TextDocument(buttonTitle, { ...opts, dropAction: undefined, title: buttonTitle, _fontSize: 37, _xMargin: 0, _yMargin: 0, ignoreClick: true, _chromeStatus: "disabled", backgroundColor: "rgba(0,0,0,0)" }) as any as Doc + // Sets up the description of the button static mobileButtonInfo = (opts: DocumentOptions, buttonInfo: string) => Docs.Create.TextDocument(buttonInfo, { ...opts, dropAction: undefined, title: "info", _fontSize: 25, _xMargin: 0, _yMargin: 0, ignoreClick: true, _chromeStatus: "disabled", backgroundColor: "rgba(0,0,0,0)", _dimMagnitude: 2, @@ -553,23 +571,6 @@ export class CurrentUserUtils { return CurrentUserUtils.setupWorkspaces(userDoc); } - static setupMobileInkingDoc(userDoc: Doc) { - return Docs.Create.FreeformDocument([], { title: "Mobile Inking", backgroundColor: "white" }); - } - - static setupMobileUploadDoc(userDoc: Doc) { - // const addButton = Docs.Create.FontIconDocument({ onDragStart: ScriptField.MakeScript('addWebToMobileUpload()'), title: "Add Web Doc to Upload Collection", icon: "plus", backgroundColor: "black" }) - const webDoc = Docs.Create.WebDocument("https://www.britannica.com/biography/Miles-Davis", { - title: "Upload Images From the Web", _chromeStatus: "enabled", lockedPosition: true - }); - const uploadDoc = Docs.Create.StackingDocument([], { - title: "Mobile Upload Collection", backgroundColor: "white", lockedPosition: true - }); - return Docs.Create.StackingDocument([webDoc, uploadDoc], { - _width: screen.width, lockedPosition: true, _chromeStatus: "disabled", title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray" - }); - } - // setup the Creator button which will display the creator panel. This panel will include the drag creators and the color picker. // when clicked, this panel will be displayed in the target container (ie, sidebarContainer) static async setupToolsBtnPanel(doc: Doc, sidebarContainer: Doc) { @@ -764,6 +765,7 @@ export class CurrentUserUtils { } } + // Right sidebar is where mobile uploads are contained static setupRightSidebar(doc: Doc) { if (doc.rightSidebarCollection === undefined) { doc.rightSidebarCollection = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "Mobile Uploads" })); @@ -823,7 +825,7 @@ export class CurrentUserUtils { this.setupDefaultIconTemplates(doc); // creates a set of icon templates triggered by the document deoration icon this.setupDocTemplates(doc); // sets up the template menu of templates this.setupRightSidebar(doc); // sets up the right sidebar collection for mobile upload documents and sharing - this.setupActiveMobileMenu(doc); + this.setupActiveMobileMenu(doc); // sets up the current mobile menu for Dash Mobile this.setupOverlays(doc); // documents in overlay layer this.setupDockedButtons(doc); // the bottom bar of font icons this.setupDefaultPresentation(doc); // presentation that's initially triggered @@ -862,9 +864,5 @@ export class CurrentUserUtils { } } -Scripting.addGlobal(function setupMobileInkingDoc(userDoc: Doc) { return CurrentUserUtils.setupMobileInkingDoc(userDoc); }, - "initializes the Mobile inking document", "(userDoc: Doc)"); -Scripting.addGlobal(function setupMobileUploadDoc(userDoc: Doc) { return CurrentUserUtils.setupMobileUploadDoc(userDoc); }, - "initializes the Mobile upload document", "(userDoc: Doc)"); Scripting.addGlobal(function createNewWorkspace() { return MainView.Instance.createNewWorkspace(); }, "creates a new workspace when called"); diff --git a/src/client/util/SettingsManager.scss b/src/client/util/SettingsManager.scss index 0116c5294..1c2a2ce05 100644 --- a/src/client/util/SettingsManager.scss +++ b/src/client/util/SettingsManager.scss @@ -137,31 +137,21 @@ @media only screen and (max-device-width: 480px) { .settings-interface { - background-color: whitesmoke !important; - color: grey; width: 80vw; height: 400px; } .settings-interface .settings-body .settings-content input { - border-radius: 5px; - border: none; font-size: 30; - padding: 4px; - min-width: 100%; - margin: 2px 0; } .settings-interface button { width: 100%; font-size: 30px; - align-self: center; background: #b2cef8; - margin-top: 4px; } .settings-interface .settings-heading { - letter-spacing: .5em; font-size: 25; } }
\ No newline at end of file diff --git a/src/client/views/AntimodeMenu.scss b/src/client/views/AntimodeMenu.scss index 17506b3dc..be21cec12 100644 --- a/src/client/views/AntimodeMenu.scss +++ b/src/client/views/AntimodeMenu.scss @@ -46,15 +46,8 @@ @media only screen and (max-device-width: 480px) { .antimodeMenu-cont { - position: absolute; - z-index: 10000; height: 100px; width: 100vw; - background: #323232; - box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25); - border-radius: 0px 6px 6px 6px; - // overflow: hidden; - display: flex; &.with-rows { flex-direction: column-reverse; @@ -79,14 +72,5 @@ .antimodeMenu-button:hover { background-color: #121212; } - - .antimodeMenu-dragger { - height: 100%; - transition: width .2s; - background-image: url("https://logodix.com/logo/1020374.png"); - background-size: 90% 100%; - background-repeat: no-repeat; - background-position: left center; - } } }
\ No newline at end of file diff --git a/src/client/views/nodes/AudioBox.scss b/src/client/views/nodes/AudioBox.scss index b5d113ca0..c959b79f5 100644 --- a/src/client/views/nodes/AudioBox.scss +++ b/src/client/views/nodes/AudioBox.scss @@ -186,18 +186,12 @@ .audiobox-container .audiobox-record, .audiobox-container-interactive .audiobox-record { - pointer-events: all; font-size: 3em; - width: 100%; - height: 100%; - position: relative; - pointer-events: none; } .audiobox-container .audiobox-controls .audiobox-player .audiobox-playhead, .audiobox-container .audiobox-controls .audiobox-player .audiobox-dictation, - .audiobox-container-interactive .audiobox-controls .audiobox-player .audiobox-playhead, - .audiobox-container-interactive .audiobox-controls .audiobox-player .audiobox-dictation { + .audiobox-container-interactive .audiobox-controls .audiobox-player .audiobox-playhead { width: 70px; } }
\ No newline at end of file diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index 974ddecdf..fbbd49a2f 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -11,18 +11,19 @@ .pdfBox-ui { position: absolute; - width: 100%; - height: 100%; - z-index: 1; - pointer-events: none; + width: 100%; + height: 100%; + z-index: 1; + pointer-events: none; - .pdfBox-pageNums { + .pdfBox-pageNums { display: flex; flex-direction: row; height: 25px; position: absolute; left: 5px; top: 5px; + .pdfBox-overlayButton-fwd, .pdfBox-overlayButton-back { background: #121721; @@ -35,29 +36,29 @@ border-radius: 3px; pointer-events: all; } - } - - .pdfBox-overlayButton { - border-bottom-left-radius: 50%; - display: flex; - justify-content: space-evenly; - align-items: center; - height: 20px; - background: none; - padding: 0; - position: absolute; - pointer-events: all; - - .pdfBox-overlayButton-arrow { - width: 0; - height: 0; - border-top: 10px solid transparent; - border-bottom: 10px solid transparent; - border-right: 15px solid #121721; - transition: all 0.5s; - } - - .pdfBox-overlayButton-iconCont { + } + + .pdfBox-overlayButton { + border-bottom-left-radius: 50%; + display: flex; + justify-content: space-evenly; + align-items: center; + height: 20px; + background: none; + padding: 0; + position: absolute; + pointer-events: all; + + .pdfBox-overlayButton-arrow { + width: 0; + height: 0; + border-top: 10px solid transparent; + border-bottom: 10px solid transparent; + border-right: 15px solid #121721; + transition: all 0.5s; + } + + .pdfBox-overlayButton-iconCont { background: #121721; height: 20px; width: 25px; @@ -222,120 +223,60 @@ } } +// CSS adjusted for mobile devices @media only screen and (max-device-width: 480px) { .pdfBox .pdfBox-ui .pdfBox-settingsCont .pdfBox-settingsButton, .pdfBox-interactive .pdfBox-ui .pdfBox-settingsCont .pdfBox-settingsButton { - border-bottom-left-radius: 50%; - display: flex; - justify-content: space-evenly; - align-items: center; height: 60px; - background: none; - padding: 0; - } - .pdfBox .pdfBox-ui .pdfBox-settingsCont .pdfBox-settingsButton .pdfBox-settingsButton-iconCont, - .pdfBox-interactive .pdfBox-ui .pdfBox-settingsCont .pdfBox-settingsButton .pdfBox-settingsButton-iconCont { - background: #121721; - height: 60px; - width: 75px; - font-size: 30px; - display: flex; - justify-content: center; - align-items: center; - margin-left: -2px; - border-radius: 3px; + .pdfBox-settingsButton-iconCont { + height: 60px; + width: 75px; + font-size: 30px; + } + + .pdfBox-settingsButton-arrow { + height: 60; + border-top: 30px solid transparent; + border-bottom: 30px solid transparent; + border-right: 30px solid #121721; + } } + + .pdfBox .pdfBox-ui .pdfBox-settingsCont .pdfBox-settingsFlyout, .pdfBox-interactive .pdfBox-ui .pdfBox-settingsCont .pdfBox-settingsFlyout { - position: absolute; - background: #323232; - box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25); - right: 20px; - border-radius: 7px; - padding: 20px; - display: flex; - flex-direction: column; font-size: 30px; - transition: all 0.5s; } - .pdfBox .pdfBox-ui .pdfBox-settingsCont, - .pdfBox-interactive .pdfBox-ui .pdfBox-settingsCont { - position: absolute; - right: 0; - top: 3; - pointer-events: all; - } - .pdfBox .pdfBox-ui .pdfBox-settingsCont .pdfBox-settingsButton .pdfBox-settingsButton-arrow, - .pdfBox-interactive .pdfBox-ui .pdfBox-settingsCont .pdfBox-settingsButton .pdfBox-settingsButton-arrow { - width: 0; - height: 60; - border-top: 30px solid transparent; - border-bottom: 30px solid transparent; - border-right: 30px solid #121721; - transition: all 0.5s; - } - - .pdfBox .pdfBox-ui .pdfBox-overlayButton .pdfBox-overlayButton-iconCont, - .pdfBox-interactive .pdfBox-ui .pdfBox-overlayButton .pdfBox-overlayButton-iconCont { - background: #121721; - height: 60px; - width: 75px; - display: flex; - font-size: 30; - position: relative; - align-items: center; - justify-content: center; - border-radius: 3px; - pointer-events: all; - } - - .pdfBox .pdfBox-ui .pdfBox-overlayButton .pdfBox-overlayButton-arrow, - .pdfBox-interactive .pdfBox-ui .pdfBox-overlayButton .pdfBox-overlayButton-arrow { - width: 0; - height: 0; - border-top: 30px solid transparent; - border-bottom: 30px solid transparent; - border-right: 30px solid #121721; - transition: all 0.5s; - } .pdfBox .pdfBox-ui .pdfBox-overlayCont, .pdfBox-interactive .pdfBox-ui .pdfBox-overlayCont { - position: absolute; - width: calc(100% - 40px); height: 60px; - background: #121721; - bottom: 0; - display: flex; - justify-content: center; - align-items: center; - overflow: hidden; - transition: left .5s; - pointer-events: all; + + .pdfBox-searchBar { + font-size: 40px; + } } .pdfBox .pdfBox-ui .pdfBox-overlayButton, .pdfBox-interactive .pdfBox-ui .pdfBox-overlayButton { - border-bottom-left-radius: 50%; - display: flex; - justify-content: space-evenly; - align-items: center; height: 60px; - background: none; - padding: 0; - position: absolute; - pointer-events: all; - } - .pdfBox .pdfBox-ui .pdfBox-overlayCont .pdfBox-searchBar, - .pdfBox-interactive .pdfBox-ui .pdfBox-overlayCont .pdfBox-searchBar { - width: 70%; - font-size: 40px; + .pdfBox-overlayButton-iconCont { + height: 60px; + width: 75px; + font-size: 30; + } + + .pdfBox-overlayButton-arrow { + border-top: 30px solid transparent; + border-bottom: 30px solid transparent; + border-right: 30px solid #121721; + } } button.pdfBox-search { @@ -348,17 +289,8 @@ .pdfBox .pdfBox-ui .pdfBox-prevIcon, .pdfBox-interactive .pdfBox-ui .pdfBox-nextIcon, .pdfBox-interactive .pdfBox-ui .pdfBox-prevIcon { - background: #121721; height: 50px; width: 50px; font-size: 30px; - display: flex; - position: relative; - align-items: center; - justify-content: center; - border-radius: 3px; - pointer-events: all; - padding: 0px; } - -} +}
\ No newline at end of file diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index 1261cbfdd..9f6af1bde 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -81,6 +81,7 @@ } } +// CSS adjusted for mobile devices @media only screen and (max-device-width: 480px) { .presBox-cont .presBox-buttons { position: absolute; @@ -92,37 +93,33 @@ z-index: 2; align-items: center; background: rgba(0, 0, 0, 0); - padding-top: 5px; - padding-bottom: 5px; display: inline-flex; + + .presBox-button { + margin-top: 5%; + height: 250; + width: 300; + font-size: 100; + display: flex; + align-items: center; + background: #323232; + color: white; + } + + .presBox-viewPicker { + top: -70; + left: 2.5%; + height: 50; + width: 95%; + font-size: 30px; + position: absolute; + min-width: 50px; + } } .presBox-cont .presBox-listCont { - position: absolute; top: 50; height: calc(100% - 80px); - width: 100%; - } - - .presBox-cont .presBox-buttons .presBox-button { - margin-top: 5%; - height: 250; - width: 300; - font-size: 100; - display: flex; - align-items: center; - background: 323232; - color: white; - } - - .presBox-cont .presBox-buttons .presBox-viewPicker { - top: -70; - left: 2.5%; - height: 50; - width: 95%; - font-size: 30px; - position: absolute; - min-width: 50px; } .input, diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/presentationview/PresElementBox.scss index 79532995e..0632f6a8b 100644 --- a/src/client/views/presentationview/PresElementBox.scss +++ b/src/client/views/presentationview/PresElementBox.scss @@ -109,89 +109,43 @@ @media only screen and (max-device-width: 480px) { .presElementBox-buttons { display: inline-flex; - position: relative; - width: 100%; + position: absolute; + top: 0; + right: 0; + z-index: 3; + width: 50%; + + .presElementBox-interaction { + width: 50; + height: 50; + } + + .presElementBox-interaction-selected { + width: 50; + height: 50; + } } .presElementBox-item { display: inline-flex; + height: max-content; overflow: hidden; } - .presElementBox-buttons .presElementBox-interaction { - color: gray; - float: left; - padding: 0px; - width: 50; - height: 50; - } - - .presElementBox-buttons .presElementBox-interaction-selected { - color: white; - float: left; - padding: 0px; - width: 50; - height: 50; - border: solid 1px darkgray; - } - .presElementBox-closeIcon { - border-radius: 20px; transform: scale(1.5); - position: absolute; right: 10; top: 10; - padding: 8px; - } - - .presElementBox-buttons { - display: inline-flex; - position: absolute; - top: 0; - right: 0; - z-index: 3; - width: 50%; } .presElementBox-name { font-size: 30px; - position: absolute; - display: inline-block; top: 10px; z-index: 3; width: 50%; - text-overflow: ellipsis; - overflow: hidden; - white-space: pre; - } - - .presElementBox-item { - display: inline-block; - background-color: #eeeeee; - pointer-events: all; - width: 100%; - min-height: 100%; - height: max-content; - outline-color: maroon; - outline-style: dashed; - border-radius: 6px; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - transition: all .1s; - padding: 0px; - padding-bottom: 3px; } .presElementBox-embedded { - position: relative; - display: flex; transform: translate(0, 90px) scale(1.5); - width: auto; - justify-content: center; - margin: auto; } }
\ No newline at end of file diff --git a/src/mobile/AudioUpload.tsx b/src/mobile/AudioUpload.tsx index 83da41d90..590bf8f9d 100644 --- a/src/mobile/AudioUpload.tsx +++ b/src/mobile/AudioUpload.tsx @@ -1,18 +1,12 @@ -import * as ReactDOM from 'react-dom'; -import * as rp from 'request-promise'; import { Docs } from '../client/documents/Documents'; import "./ImageUpload.scss"; import React = require('react'); -import { DocServer } from '../client/DocServer'; import { observer } from 'mobx-react'; import { observable, action, computed } from 'mobx'; import { Utils, emptyPath, returnFalse, emptyFunction, returnOne, returnZero, returnTrue, returnEmptyFilter } from '../Utils'; -import { Networking } from '../client/Network'; import { Doc, Opt } from '../fields/Doc'; import { Cast, FieldValue } from '../fields/Types'; import { listSpec } from '../fields/Schema'; -import { List } from '../fields/List'; -import { Scripting } from '../client/util/Scripting'; import MainViewModal from '../client/views/MainViewModal'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { nullAudio } from '../fields/URLField'; @@ -23,40 +17,56 @@ import { DictationOverlay } from '../client/views/DictationOverlay'; import RichTextMenu from '../client/views/nodes/formattedText/RichTextMenu'; import { ContextMenu } from '../client/views/ContextMenu'; -export interface ImageUploadProps { - Document: Doc; -} - -// const onPointerDown = (e: React.TouchEvent) => { -// let imgInput = document.getElementById("input_image_file"); -// if (imgInput) { -// imgInput.click(); -// } -// } -const inputRef = React.createRef<HTMLInputElement>(); - @observer export class AudioUpload extends React.Component { - @observable error: string = ""; - @observable status: string = ""; - @observable nm: string = "Choose files"; - @observable process: string = ""; - @observable public _audioCol: Doc = FieldValue(Cast(Docs.Create.FreeformDocument([Cast(Docs.Create.AudioDocument(nullAudio, { title: "mobile audio", _width: 500, _height: 100 }), Doc) as Doc], { title: "mobile audio", _fitToBox: true, boxShadow: "0 0" }), Doc)) as Doc; - + @observable public _audioCol: Doc = FieldValue(Cast(Docs.Create.FreeformDocument([Cast(Docs.Create.AudioDocument(nullAudio, { title: "mobile audio", _width: 500, _height: 100 }), Doc) as Doc], { title: "mobile audio", _width: 300, _height: 300, _fitToBox: true, boxShadow: "0 0" }), Doc)) as Doc; + /** + * Handles the onclick functionality for the 'Restart' button + * Resets the document to its default view + */ @action clearUpload = () => { for (let i = 1; i < 8; i++) { this.setOpacity(i, "0.2"); } - this._audioCol = FieldValue(Cast(Docs.Create.FreeformDocument([Cast(Docs.Create.AudioDocument(nullAudio, { title: "mobile audio", _width: 500, _height: 100 }), Doc) as Doc], { title: "mobile audio", _fitToBox: true, boxShadow: "0 0" }), Doc)) as Doc; + this._audioCol = FieldValue(Cast( + Docs.Create.FreeformDocument( + [Cast(Docs.Create.AudioDocument(nullAudio, { + title: "mobile audio", + _width: 500, + _height: 100 + }), Doc) as Doc], { title: "mobile audio", _width: 300, _height: 300, _fitToBox: true, boxShadow: "0 0" }), Doc)) as Doc; } + /** + * Handles the onClick of the 'Close' button + * Reset upload interface and toggle audio + */ closeUpload = () => { this.clearUpload(); MobileInterface.Instance.toggleAudio(); } + /** + * Handles the on click of the 'Upload' button. + * Pushing the audio doc onto Dash Web through the right side bar + */ + uploadAudio = () => { + const audioRightSidebar = Cast(Doc.UserDoc().rightSidebarCollection, Doc) as Doc; + const audioDoc = this._audioCol; + const data = Cast(audioRightSidebar.data, listSpec(Doc)); + for (let i = 1; i < 8; i++) { + setTimeout(() => this.setOpacity(i, "1"), i * 200); + } + if (data) { + data.push(audioDoc); + } + // Resets uploader after 3 seconds + setTimeout(this.clearUpload, 3000); + } + + // Returns the upload audio menu private get uploadInterface() { return ( <> @@ -114,30 +124,14 @@ export class AudioUpload extends React.Component { ); } - setOpacity = (i: number, o: string) => { - const slab = document.getElementById("slab0" + i); + // Handles the setting of the loading bar + setOpacity = (index: number, opacity: string) => { + const slab = document.getElementById("slab0" + index); if (slab) { - console.log(slab?.id); - slab.style.opacity = o; + slab.style.opacity = opacity; } } - // Pushing the audio doc onto Dash Web through the right side bar - uploadAudio = () => { - console.log("uploading"); - const audioRightSidebar = Cast(Doc.UserDoc().rightSidebarCollection, Doc) as Doc; - const audioDoc = this._audioCol; - const data = Cast(audioRightSidebar.data, listSpec(Doc)); - for (let i = 1; i < 8; i++) { - setTimeout(() => this.setOpacity(i, "1"), i * 200); - } - if (data) { - data.push(audioDoc); - } - - setTimeout(this.clearUpload, 3000); - } - @observable private dialogueBoxOpacity = 1; @observable private overlayOpacity = 0.4; diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index 6a5a2dd5b..5ea626d52 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -1,4 +1,3 @@ -import * as ReactDOM from 'react-dom'; import * as rp from 'request-promise'; import { Docs } from '../client/documents/Documents'; import "./ImageUpload.scss"; @@ -12,49 +11,38 @@ import { Doc, Opt } from '../fields/Doc'; import { Cast } from '../fields/Types'; import { listSpec } from '../fields/Schema'; import { List } from '../fields/List'; -import { Scripting } from '../client/util/Scripting'; import MainViewModal from '../client/views/MainViewModal'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { MobileInterface } from './MobileInterface'; -import { CurrentUserUtils } from '../client/util/CurrentUserUtils'; export interface ImageUploadProps { - Document: Doc; + Document: Doc; // Target document for upload (upload location) } -// const onPointerDown = (e: React.TouchEvent) => { -// let imgInput = document.getElementById("input_image_file"); -// if (imgInput) { -// imgInput.click(); -// } -// } const inputRef = React.createRef<HTMLInputElement>(); @observer export class Uploader extends React.Component<ImageUploadProps> { @observable error: string = ""; - @observable status: string = ""; - @observable nm: string = "Choose files"; - @observable process: string = ""; + @observable nm: string = "Choose files"; // Text of 'Choose Files' button + @observable process: string = ""; // Current status of upload onClick = async () => { try { const col = this.props.Document; await Docs.Prototypes.initialize(); const imgPrev = document.getElementById("img_preview"); - // Slab 1 - this.setOpacity(1, "1"); + this.setOpacity(1, "1"); // Slab 1 if (imgPrev) { const files: FileList | null = inputRef.current!.files; - // Slab 2 - this.setOpacity(2, "1"); + this.setOpacity(2, "1"); // Slab 2 if (files && files.length !== 0) { this.process = "Uploading Files"; for (let index = 0; index < files.length; ++index) { const file = files[index]; const res = await Networking.UploadFilesToServer(file); - // Slab 3 - this.setOpacity(3, "1"); + this.setOpacity(3, "1"); // Slab 3 + // For each item that the user has selected res.map(async ({ result }) => { const name = file.name; if (result instanceof Error) { @@ -62,16 +50,17 @@ export class Uploader extends React.Component<ImageUploadProps> { } const path = Utils.prepend(result.accessPaths.agnostic.client); let doc = null; - console.log("type: " + file.type); + // Case 1: File is a video if (file.type === "video/mp4") { doc = Docs.Create.VideoDocument(path, { _nativeWidth: 400, _width: 400, title: name }); + // Case 2: File is a PDF document } else if (file.type === "application/pdf") { doc = Docs.Create.PdfDocument(path, { _nativeWidth: 400, _width: 400, title: name }); + // Case 3: File is another document type (most likely Image) } else { doc = Docs.Create.ImageDocument(path, { _nativeWidth: 400, _width: 400, title: name }); } - // Slab 4 - this.setOpacity(4, "1"); + this.setOpacity(4, "1"); // Slab 4 const res = await rp.get(Utils.prepend("/getUserDocumentId")); if (!res) { throw new Error("No user id returned"); @@ -79,32 +68,27 @@ export class Uploader extends React.Component<ImageUploadProps> { const field = await DocServer.GetRefField(res); let pending: Opt<Doc>; if (field instanceof Doc) { - // if (col === Cast(Doc.UserDoc().rightSidebarCollection, Doc) as Doc) { - // pending = await Cast(field.rightSidebarCollection, Doc); - // } pending = col; - //pending = await Cast(field.col, Doc); } if (pending) { const data = await Cast(pending.data, listSpec(Doc)); if (data) data.push(doc); else pending.data = new List([doc]); - this.status = "finished"; this.setOpacity(5, "1"); // Slab 5 this.process = "File " + (index + 1).toString() + " Uploaded"; this.setOpacity(6, "1"); // Slab 6 - this.setOpacity(7, "1"); // Slab 7 } - console.log("i: " + index + 1); - console.log("l: " + files.length); if ((index + 1) === files.length) { this.process = "Uploads Completed"; + this.setOpacity(7, "1"); // Slab 7 } }); } + // Case in which the user pressed upload and no files were selected } else { this.process = "No file selected"; } + // Three seconds after upload the menu will reset setTimeout(this.clearUpload, 3000); } } catch (error) { @@ -117,14 +101,13 @@ export class Uploader extends React.Component<ImageUploadProps> { const files: FileList | null = inputRef.current!.files; await files; if (files && files.length === 1) { - console.log(files); this.nm = files[0].name; } else if (files && files.length > 1) { - console.log(files.length); this.nm = files.length.toString() + " files selected"; } } + // Loops through load icons, and resets buttons @action clearUpload = () => { for (let i = 1; i < 8; i++) { @@ -136,23 +119,21 @@ export class Uploader extends React.Component<ImageUploadProps> { inputRef.current.value = ""; } this.process = ""; - console.log(inputRef.current!.files); } + // Clears the upload and closes the upload menu closeUpload = () => { this.clearUpload(); MobileInterface.Instance.toggleUpload(); } - setOpacity = (i: number, o: string) => { - const slab = document.getElementById("slab" + i); - if (slab) { - console.log(slab?.id); - slab.style.opacity = o; - } + // Handles the setting of the loading bar + setOpacity = (index: number, opacity: string) => { + const slab = document.getElementById("slab" + index); + if (slab) slab.style.opacity = opacity; } - + // Returns the upload interface for mobile private get uploadInterface() { return ( <div className="imgupload_cont"> diff --git a/src/mobile/MobileHome.scss b/src/mobile/MobileHome.scss deleted file mode 100644 index e1566b622..000000000 --- a/src/mobile/MobileHome.scss +++ /dev/null @@ -1,101 +0,0 @@ -$navbar-height: 120px; -$pathbar-height: 50px; - -* { - margin: 0px; - padding: 0px; - box-sizing: border-box; - font-family: "Open Sans"; -} - -.homeContainer { - position: relative; - top: 200px; - overflow: scroll; - width: 100%; - left: 0; - height: calc(100% - 120px); - overflow-y: scroll; -} - -.homeButton { - width: 96%; - margin-left: 2.5%; - height: 250px; - border-radius: 30px; - margin-top: 15px; - margin-bottom: 15px; -} - -.iconRight { - position: absolute; - width: 50%; - height: 80px; - transform: translate(0, 50%); - right: 0px; - text-align: center; - font-size: 80; -} - -.iconLeft { - position: absolute; - width: 50%; - height: 80px; - transform: translate(0%, 50%); - left: 0px; - text-align: center; - font-size: 80; -} - -.textLeft { - position: absolute; - width: 50%; - left: 0px; - font-size: 40px; - text-align: left; - margin-left: 110px; - margin-top: 40px; - font-family: sans-serif; - font-weight: bold; -} - -.textRight { - position: absolute; - width: 50%; - right: 0px; - font-size: 40px; - text-align: right; - margin-right: 110px; - margin-top: 40px; - font-family: sans-serif; - font-weight: bold; -} - -.menuView { - position: absolute; - top: 135px; - left: 50%; - transform: translate(-50%, 0%); - display: flex; -} - -.iconView { - height: 60px; - width: 60px; - background-color: darkgray; - border-radius: 5px; - border-style: solid; - border-width: 2px; - border-color: black; -} - -.listView { - height: 60px; - width: 60px; - margin-left: 20; - background-color: darkgray; - border-radius: 5px; - border-style: solid; - border-width: 2px; - border-color: black; -}
\ No newline at end of file diff --git a/src/mobile/MobileInterface.scss b/src/mobile/MobileInterface.scss index 86b043590..ee39d4f50 100644 --- a/src/mobile/MobileInterface.scss +++ b/src/mobile/MobileInterface.scss @@ -1,36 +1,444 @@ -.mobileInterface-inkInterfaceButtons { - position: absolute; - top: 0px; - display: flex; - justify-content: space-between; - width: 100%; - z-index: 9999; - height: 50px; +$navbar-height: 120px; +$pathbar-height: 50px; - .mobileInterface-button { - height: 100%; +@media only screen and (max-device-width: 480px) { + * { + margin: 0px; + padding: 0px; + box-sizing: border-box; + font-family: sans-serif; } } +body { + overflow: hidden; +} + .mobileInterface-container { height: 100%; position: relative; touch-action: none; width: 100%; - -webkit-touch-callout:none; - -webkit-user-select:none; - -khtml-user-select:none; - -moz-user-select:none; - -ms-user-select:none; - user-select:none; - -webkit-tap-highlight-color:rgba(0,0,0,0); + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +// Topbar of Dash Mobile +.navbar { + position: fixed; + top: 0px; + left: 0px; + width: 100vw; + height: $navbar-height; + background-color: whitesmoke; + z-index: 150; + + .cover { + position: absolute; + right: 0px; + top: 0px; + height: 120px; + width: 120px; + background-color: whitesmoke; + z-index: 200; + } + + .toggle-btn { + position: absolute; + right: 20px; + top: 30px; + height: 70px; + width: 70px; + transition: all 400ms ease-in-out 200ms; + z-index: 180; + } + + .background { + position: absolute; + right: 0px; + top: 0px; + height: 120px; + width: 120px; + //border: 1px solid black; + } + + .background.active { + background-color: lightgrey; + } + + .toggle-btn-home { + right: -200px; + } + + .header { + position: absolute; + top: 50%; + top: calc(9px + 50%); + right: 50%; + transform: translate(50%, -50%); + font-size: 40; + font-weight: 700; + text-align: center; + user-select: none; + text-transform: uppercase; + font-family: Arial, Helvetica, sans-serif; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + direction: ltr; + width: 600px; + } + + .toggle-btn span { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 70%; + height: 4px; + background: black; + transition: all 200ms ease; + z-index: 180; + } + + .toggle-btn span:nth-child(1) { + transition: top 200ms ease-in-out; + top: 30%; + } + + .toggle-btn span:nth-child(3) { + transition: top 200ms ease-in-out; + top: 70%; + } + + .toggle-btn.active { + transition: transform 200ms ease-in-out 200ms; + transform: rotate(135deg); + } + + .toggle-btn.active span:nth-child(1) { + top: 50%; + } + + .toggle-btn.active span:nth-child(2) { + transform: translate(-50%, -50%) rotate(90deg); + } + + .toggle-btn.active span:nth-child(3) { + top: 50%; + } +} + +.sidebar { + position: fixed; + top: 120px; + opacity: 0; + right: -100%; + width: 80%; + height: calc(80% - (120px)); + z-index: 101; + background-color: whitesmoke; + transition: all 400ms ease 50ms; + padding: 20px; + box-shadow: 0 0 5px 5px grey; + + .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; + display: inline-flex; + font-size: 35px; + text-transform: uppercase; + color: black; + } + + .ink:focus { + outline: 1px solid blue; + } + + .sidebarButtons { + top: 80px; + position: relative; + } +} + + + + + + +.blanket { + position: fixed; + top: 120px; + opacity: 0.5; + right: -100%; + width: 100%; + height: calc(100% - (120px)); + z-index: 101; + background-color: grey; + padding: 20px; +} + +.blanket.active { + position: absolute; + right: 0%; + z-index: 100; +} + +.home { + position: absolute; + top: 30px; + left: 30px; + font-size: 60; + user-select: none; + text-transform: uppercase; + font-family: Arial, Helvetica, sans-serif; + z-index: 200; } -.mobileInterface-background { +.item-type { + display: inline; + text-transform: lowercase; + margin-left: 20px; + font-size: 35px; + font-style: italic; + color: rgb(28, 28, 28); +} + +.item-title { + max-width: 70%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.right { + margin-left: 20px; + z-index: 200; +} + +.open { + right: 20px; + font-size: 35; + position: absolute; +} + +.left { + width: 100%; height: 100%; +} + + + +.sidebar.active { + position: absolute; + right: 0%; + opacity: 1; + z-index: 101; +} + +.back { + position: absolute; + left: 42px; + top: 0; + background: #1a1a1a; + width: 50px; + height: 100%; + display: flex; + justify-content: center; + text-align: center; + flex-direction: column; + align-items: center; + border-radius: 10px; + font-size: 25px; + user-select: none; + z-index: 100; +} + +.pathbar { + position: fixed; + top: 118px; + left: 0px; + background: #1a1a1a; + z-index: 120; + border-radius: 0px; width: 100%; + height: 80px; + overflow: hidden; + + .pathname { + position: relative; + font-size: 25; + top: 50%; + width: 86%; + left: 12%; + 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; + } + + .scrollmenu { + overflow: auto; + width: 100%; + height: 100%; + white-space: nowrap; + display: inline-flex; + } + + .hidePath { + position: absolute; + height: 100%; + width: 200px; + left: 0px; + top: 0px; + background-image: linear-gradient(to right, #1a1a1a, rgba(0, 0, 0, 0)); + text-align: center; + user-select: none; + z-index: 99; + pointer-events: none; + } + + .pathbarItem { + position: relative; + display: flex; + align-items: center; + color: whitesmoke; + text-align: center; + justify-content: center; + user-select: none; + transform: translate(100px, 0px); + font-size: 30px; + padding: 10px; + text-transform: uppercase; + + .pathbarText { + font-family: sans-serif; + text-align: center; + height: 50px; + padding: 10px; + font-size: 30px; + border-radius: 10px; + text-transform: uppercase; + margin-left: 20px; + position: relative; + } + + .pathIcon { + transform: translate(0px, 0px); + position: relative; + } + } +} + + +/** +* docButton appears at the bottom of mobile document +* Buttons include: pin to presentation, download, upload, reload +*/ +.docButton { position: relative; - touch-action: none; - background-color: pink; + width: 100px; + display: flex; + height: 100px; + font-size: 70px; + text-align: center; + border: 3px solid black; + margin: 20px; + z-index: 100; + border-radius: 100%; + justify-content: center; + flex-direction: column; + align-items: center; +} + +.docButtonContainer { + top: 80%; + position: absolute; + display: flex; + transform: translate(-50%, 0); + left: 50%; + z-index: 100; } + +.toolbar { + left: 50%; + transform: translate(-50%); + position: absolute; + height: max-content; + top: 0px; + border-radius: 20px; + background-color: lightgrey; + opacity: 0; + transition: all 400ms ease 50ms; +} + +.toolbar.active { + display: inline-block; + width: 300px; + padding: 5px; + opacity: 1; + height: max-content; + top: -450px; +} + +.colorSelector { + position: absolute; + top: 550px; + left: 300px; + transform: translate(-50%, 0); + z-index: 100; + display: inline-flex; + width: max-content; + height: max-content; + pointer-events: all; + font-size: 90px; +} + +// Menu buttons for toggling between list and icon view +.homeSwitch { + position: fixed; + top: 212; + right: 36px; + display: inline-flex; + width: max-content; + z-index: 99; + height: 70px; + + .list { + width: 70px; + height: 70px; + margin: 5; + padding: 10; + align-items: center; + text-align: center; + font-size: 50; + border-style: solid; + border-width: 3; + border-color: black; + background: whitesmoke; + align-self: center; + border-radius: 10px; + } + + .list.active { + color: darkred; + border-color: darkred; + } +}
\ No newline at end of file diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 90672e19f..38705898b 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -11,42 +11,30 @@ import { import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; -import { trace } from 'mobx'; -import * as rp from 'request-promise'; import { Doc, DocListCast } from '../fields/Doc'; import { CurrentUserUtils } from '../client/util/CurrentUserUtils'; import { emptyFunction, emptyPath, returnEmptyString, returnFalse, returnOne, returnTrue, returnZero, returnEmptyFilter } from '../Utils'; -import { DocServer } from '../client/DocServer'; import { Docs, DocumentOptions } from '../client/documents/Documents'; import { Scripting } from '../client/util/Scripting'; import { DocumentView } from '../client/views/nodes/DocumentView'; import { Transform } from '../client/util/Transform'; import "./MobileInterface.scss"; -import "./MobileMenu.scss"; -import "./MobileHome.scss"; import "./ImageUpload.scss"; import "./AudioUpload.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 } from '../fields/URLField'; import GestureOverlay from "../client/views/GestureOverlay"; import { ScriptField } from "../fields/ScriptField"; import InkOptionsMenu from "../client/views/collections/collectionFreeForm/InkOptionsMenu"; import { RadialMenu } from "../client/views/nodes/RadialMenu"; -import { UndoManager, undoBatch } from "../client/util/UndoManager"; -import { MainView } from "../client/views/MainView"; +import { UndoManager } from "../client/util/UndoManager"; import { List } from "../fields/List"; import { AudioUpload } from "./AudioUpload"; import { Cast, FieldValue } from '../fields/Types'; -import { CollectionView } from '../client/views/collections/CollectionView'; -import { InkingStroke } from '../client/views/InkingStroke'; import RichTextMenu from "../client/views/nodes/formattedText/RichTextMenu"; import { AudioBox } from "../client/views/nodes/AudioBox"; -import { FormattedTextBox } from "../client/views/nodes/formattedText/FormattedTextBox"; 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, @@ -82,22 +70,15 @@ export class MobileInterface extends React.Component { @action componentDidMount = () => { - // Doc.UserDoc().activeMobile = this._homeDoc; + // if the home menu is in list view -> adjust the menu toggle appropriately this._homeDoc._viewType === "stacking" ? this.menuListView = true : this.menuListView = false; - Doc.SetSelectedTool(InkTool.None); - Doc.UserDoc().activeMobile = this._homeDoc; + 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); - document.addEventListener("dash", (e: any) => { // event used by chrome plugin to tell Dash which document to focus on - const id = FormattedTextBox.GetDocFromUrl(e.detail); - DocServer.GetRefField(id).then(doc => { - if (doc instanceof Doc) { - DocumentManager.Instance.jumpToDocument(doc, false, undefined); - } - }); - }); } @action @@ -123,6 +104,8 @@ export class MobileInterface extends React.Component { onSwitch && onSwitch(); this.renderView = renderView; + // Ensures that switching to home is not registed + UndoManager.undoStack.length = 0; } // For toggling the hamburger menu @@ -144,16 +127,18 @@ export class MobileInterface extends React.Component { */ back = () => { const header = document.getElementById("header") as HTMLElement; - const doc = Cast(this._parents.pop(), Doc) as Doc; - + 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.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; @@ -162,11 +147,11 @@ export class MobileInterface extends React.Component { header.textContent = String(doc.title); } } - this._ink = false; + this._ink = false; // turns ink off } /** - * Return 'Home", which implies returning to 'Home' buttons + * Return 'Home", which implies returning to 'Home' menu buttons */ returnHome = () => { if (!this._homeMenu || this.sidebarActive) { @@ -258,11 +243,16 @@ export class MobileInterface extends React.Component { } } + /** + * 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 + */ openFromSidebar = (doc: Doc) => { this._parents.push(this._activeDoc); this.switchCurrentView(doc); this._homeMenu = false; - this._child = doc; //? + this._child = doc; this.toggleSidebar(); } @@ -378,12 +368,12 @@ export class MobileInterface extends React.Component { </div> ); } - + // stores workspace documents as 'workspaces' variable let workspaces = Cast(this.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 ( @@ -445,7 +435,7 @@ export class MobileInterface extends React.Component { } /** - * Handles the Create New Workspace button in the menu (taken from MainView.tsx) + * Handles the 'Create New Workspace' button in the menu (taken from MainView.tsx) */ @action createNewWorkspace = async (id?: string) => { @@ -467,7 +457,6 @@ export class MobileInterface extends React.Component { workspaceDoc.contextMenuLabels = new List<string>(["Toggle Theme Colors", "Toggle Comic Mode", "New Workspace Layout"]); Doc.AddDocToList(workspaces, "data", workspaceDoc); - // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container) } stop = (e: React.MouseEvent) => { @@ -508,7 +497,6 @@ export class MobileInterface extends React.Component { inkMenu = () => { if (this._activeDoc._viewType === "docking") { if (this._ink) { - console.log("here"); return <div className="colorSelector"> <InkOptionsMenu /> </div>; @@ -517,9 +505,9 @@ export class MobileInterface extends React.Component { } } - + // uses UndoManager and handles the color change opacity change if CanUndo is true undo = () => { - if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc && this._activeDoc.title !== "WORKSPACES") { + if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc && this._activeDoc !== this.userDoc.rightSidebarCollection && this._activeDoc.title !== "WORKSPACES") { return (<> <div className="docButton" style={{ backgroundColor: "black", color: "white", fontSize: "60", opacity: UndoManager.CanUndo() ? "1" : "0.4", }} @@ -535,8 +523,9 @@ export class MobileInterface extends React.Component { } } + // uses UndoManager and handles the color change opacity change if CanRedo is true redo = () => { - if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc && this._activeDoc.title !== "WORKSPACES") { + if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc && this._activeDoc !== this.userDoc.rightSidebarCollection && this._activeDoc.title !== "WORKSPACES") { return (<> <div className="docButton" style={{ backgroundColor: "black", color: "white", fontSize: "60", opacity: UndoManager.CanRedo() ? "1" : "0.4", }} @@ -576,6 +565,7 @@ export class MobileInterface extends React.Component { <div className="docButton" id="uploadButton" title={"uploadFile"} + style={{ backgroundColor: "white", color: "black" }} onClick={this.toggleUpload}> <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="upload" /> @@ -593,7 +583,6 @@ export class MobileInterface extends React.Component { style={{ backgroundColor: "white", color: "black" }} onClick={e => { window.open(url); - console.log(url); }}> <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="download" /> @@ -647,18 +636,13 @@ export class MobileInterface extends React.Component { 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); }); } } @@ -670,22 +654,18 @@ export class MobileInterface extends React.Component { 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); }); } } // For setting up the presentation document for the home menu setupDefaultPresentation = () => { - const presentation = Cast(Doc.UserDoc().activePresentation, Doc) as Doc; if (presentation) { @@ -698,10 +678,11 @@ export class MobileInterface extends React.Component { @action toggleUpload = () => this.imageUploadActive = !this.imageUploadActive - // For toggling image upload pop up + // 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; @@ -719,12 +700,6 @@ export class MobileInterface extends React.Component { // Returns the image upload pop up uploadImage = () => { - if (this.imageUploadActive) { - console.log("active"); - } else if (!this.imageUploadActive) { - - } - let doc; let toggle; if (this._homeMenu === false) { @@ -739,6 +714,7 @@ export class MobileInterface extends React.Component { ); } + // Radial menu can only be used if it is a colleciton and it is not a homeDoc displayRadialMenu = () => { if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc) { return <RadialMenu />; @@ -750,6 +726,7 @@ export class MobileInterface extends React.Component { e.stopPropagation(); } + // Button that appears on the bottom of the screen to initiate image upload uploadImageButton = () => { if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc && this._activeDoc._viewType !== "docking" && this._activeDoc.title !== "WORKSPACES") { return <div className="docButton" @@ -762,6 +739,11 @@ export class MobileInterface extends React.Component { } } + /** + * MENU BUTTON + * Switch view from mobile menu to access the mobile uploads + * Global function name: openMobileUploads() + */ switchToMobileUploads = () => { const mobileUpload = Cast(Doc.UserDoc().rightSidebarCollection, Doc) as Doc; this.switchCurrentView(mobileUpload); @@ -800,14 +782,20 @@ export class MobileInterface extends React.Component { } - +//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 mobile, (doc: any)"); -Scripting.addGlobal(function openMobilePresentation() { return MobileInterface.Instance.setupDefaultPresentation(); }, - "opens the presentation on mobile"); -Scripting.addGlobal(function toggleMobileSidebar() { return MobileInterface.Instance.toggleSidebar(); }); -Scripting.addGlobal(function openMobileAudio() { return MobileInterface.Instance.toggleAudio(); }); -Scripting.addGlobal(function openMobileSettings() { return SettingsManager.Instance.open(); }); -Scripting.addGlobal(function uploadImageMobile() { return MobileInterface.Instance.toggleUpload(); }); -Scripting.addGlobal(function switchToMobileUploads() { return MobileInterface.Instance.switchToMobileUploads(); }); -Scripting.addGlobal(function switchToMobileLibrary() { return MobileInterface.Instance.switchToLibrary(); });
\ No newline at end of file + "changes the active document displayed on the Dash Mobile", "(doc: any)"); diff --git a/src/mobile/MobileMenu.scss b/src/mobile/MobileMenu.scss index b60aa308f..e69de29bb 100644 --- a/src/mobile/MobileMenu.scss +++ b/src/mobile/MobileMenu.scss @@ -1,475 +0,0 @@ -$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; - z-index: 150; -} - -.navbar .cover { - position: absolute; - right: 0px; - top: 0px; - height: 120px; - width: 120px; - background-color: whitesmoke; - z-index: 200; -} - -.navbar .toggle-btn { - position: absolute; - right: 20px; - top: 30px; - height: 70px; - width: 70px; - transition: all 400ms ease-in-out 200ms; - z-index: 180; -} - -.navbar .background { - position: absolute; - right: 0px; - top: 0px; - height: 120px; - width: 120px; - //border: 1px solid black; -} - -.navbar .background.active { - background-color: lightgrey; -} - -.navbar .toggle-btn-home { - right: -200px; -} - -.navbar .header { - position: absolute; - top: 50%; - top: calc(9px + 50%); - right: 50%; - transform: translate(50%, -50%); - font-size: 40; - font-weight: 700; - text-align: center; - user-select: none; - text-transform: uppercase; - font-family: Arial, Helvetica, sans-serif; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - direction: ltr; - width: 600px; -} - -.navbar .toggle-btn span { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 70%; - height: 4px; - background: black; - transition: all 200ms ease; - z-index: 180; -} - -.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: fixed; - top: 120px; - opacity: 0; - right: -100%; - width: 80%; - height: calc(80% - (120px)); - z-index: 101; - background-color: whitesmoke; - transition: all 400ms ease 50ms; - padding: 20px; - // overflow-y: auto; - // -webkit-overflow-scrolling: touch; - // border-right: 5px solid black; - box-shadow: 0 0 5px 5px grey; -} - -.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; - display: inline-flex; - font-size: 35px; - text-transform: uppercase; - color: black; - -} - -.sidebar .ink:focus { - outline: 1px solid blue; -} - -.sidebarButtons { - top: 80px; - position: relative; -} - -.blanket { - position: fixed; - top: 120px; - opacity: 0.5; - right: -100%; - width: 100%; - height: calc(100% - (120px)); - z-index: 101; - background-color: grey; - padding: 20px; -} - -.blanket.active { - position: absolute; - right: 0%; - z-index: 100; -} - -.home { - position: absolute; - top: 30px; - left: 30px; - font-size: 60; - user-select: none; - text-transform: uppercase; - font-family: Arial, Helvetica, sans-serif; - z-index: 200; -} - -.item-type { - display: inline; - text-transform: lowercase; - margin-left: 20px; - font-size: 35px; - font-style: italic; - color: rgb(28, 28, 28); -} - -.item-title { - max-width: 70%; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.right { - margin-left: 20px; - z-index: 200; -} - -.open { - right: 20px; - font-size: 35; - position: absolute; -} - -.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 { - position: absolute; - right:0%; - opacity: 1; - z-index: 101; -} - -.back { - position: absolute; - left: 42px; - top: 0; - background: #1a1a1a; - width: 50px; - height: 100%; - display: flex; - justify-content: center; - text-align: center; - flex-direction: column; - align-items: center; - border-radius: 10px; - font-size: 25px; - user-select: none; - z-index: 100; -} - -.pathbar { - position: fixed; - top: 118px; - left: 0px; - background: #1a1a1a; - z-index: 120; - border-radius: 0px; - width: 100%; - height: 80px; - overflow: hidden; -} - -.pathname { - position: relative; - font-size: 25; - top: 50%; - width: 86%; - left: 12%; - 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; -} - -.docButton { - position: relative; - width: 100px; - display: flex; - height: 100px; - font-size: 70px; - text-align: center; - border: 3px solid black; - margin: 20px; - z-index: 100; - border-radius: 100%; - justify-content: center; - flex-direction: column; - align-items: center; -} - -.docButtonContainer { - top: 80%; - position: absolute; - display: flex; - transform: translate(-50%, 0); - left: 50%; - z-index: 100; -} - -.scrollmenu { - overflow: auto; - width: 100%; - height: 100%; - white-space: nowrap; - display: inline-flex; -} - -.pathbarItem { - position: relative; - display: flex; - align-items: center; - color: whitesmoke; - text-align: center; - justify-content: center; - user-select: none; - transform: translate(100px, 0px); - font-size: 30px; - padding: 10px; - text-transform: uppercase; -} - -.pathbarText { - font-family: sans-serif; - text-align: center; - height: 50px; - padding: 10px; - font-size: 30px; - border-radius: 10px; - text-transform: uppercase; - margin-left: 20px; - position: relative; -} - - -.pathIcon { - transform: translate(0px, 0px); - position: relative; -} - -.hidePath { - position: absolute; - height: 100%; - width: 200px; - left: 0px; - top: 0px; - background-image: linear-gradient(to right, #1a1a1a, rgba(0, 0, 0, 0)); - text-align: center; - user-select: none; - z-index: 99; - pointer-events: none; -} - -.toolbar { - left: 50%; - transform: translate(-50%); - position: absolute; - height: max-content; - top: 0px; - border-radius: 20px; - background-color: lightgrey; - opacity: 0; - transition: all 400ms ease 50ms; -} - -.toolbar.active { - display: inline-block; - width: 300px; - padding: 5px; - opacity: 1; - height: max-content; - top: -450px; -} - -.colorSelector { - position: absolute; - top: 550px; - left: 300px; - transform: translate(-50%, 0); - z-index: 100; - display: inline-flex; - width: max-content; - height: max-content; - pointer-events: all; - font-size: 90px; -} - -.widthSelector { - display: inline-flex; - width: max-content; - height: 100px; - padding: 10px; -} - -.slider { - -webkit-appearance: none; - /* Override default CSS styles */ - appearance: none; - width: 100%; - /* Full-width */ - height: 25px; - /* Specified height */ - background: #d3d3d3; - /* Grey background */ - outline: none; - /* Remove outline */ -} - -.colorButton { - width: 70px; - margin: 10px; - height: 70px; - border-style: solid; - border-width: 3px; - border-radius: 100%; -} - -.homeSwitch { - position: fixed; - top: 212; - right: 36px; - display: inline-flex; - width: max-content; - z-index: 99; - height: 70px; -} - -.list { - width: 70px; - height: 70px; - margin: 5; - padding: 10; - align-items: center; - text-align: center; - font-size: 50; - border-style: solid; - border-width: 3; - border-color: black; - background: whitesmoke; - align-self: center; - border-radius: 10px; -} - -.list.active { - color: darkred; - border-color: darkred; -}
\ No newline at end of file |