From 1a6feb447f9c4fd461ba02dc45a93e569a283be0 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Sat, 6 Jun 2020 00:04:54 -0700 Subject: initial commit --- src/mobile/ImageUpload.tsx | 74 +++++++++++++++------------------------------- 1 file changed, 24 insertions(+), 50 deletions(-) (limited to 'src/mobile/ImageUpload.tsx') diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index b15042f9f..c35c4a917 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -4,16 +4,18 @@ import { Docs } from '../client/documents/Documents'; import "./ImageUpload.scss"; import React = require('react'); import { DocServer } from '../client/DocServer'; -import { Opt, Doc } from '../fields/Doc'; -import { Cast } from '../fields/Types'; -import { listSpec } from '../fields/Schema'; -import { List } from '../fields/List'; import { observer } from 'mobx-react'; import { observable } from 'mobx'; import { Utils } from '../Utils'; -import MobileInterface from './MobileInterface'; -import { CurrentUserUtils } from '../client/util/CurrentUserUtils'; -import { resolvedPorts } from '../client/views/Main'; +import { Networking } from '../client/Network'; +import { Doc, Opt } from '../fields/Doc'; +import { Cast } from '../fields/Types'; +import { listSpec } from '../fields/Schema'; +import { List } from '../fields/List'; + +export interface ImageUploadProps { + Document: Doc; +} // const onPointerDown = (e: React.TouchEvent) => { // let imgInput = document.getElementById("input_image_file"); @@ -24,7 +26,7 @@ import { resolvedPorts } from '../client/views/Main'; const inputRef = React.createRef(); @observer -class Uploader extends React.Component { +export class Uploader extends React.Component { @observable error: string = ""; @observable status: string = ""; @@ -39,20 +41,15 @@ class Uploader extends React.Component { if (files && files.length !== 0) { console.log(files[0]); const name = files[0].name; - const formData = new FormData(); - formData.append("file", files[0]); - - const upload = window.location.origin + "/uploadFormData"; + const res = await Networking.UploadFilesToServer(files[0]); this.status = "uploading image"; - console.log("uploading image", formData); - const res = await fetch(upload, { - method: 'POST', - body: formData - }); this.status = "upload image, getting json"; - const json = await res.json(); - json.map(async (file: any) => { - const path = window.location.origin + file; + + res.map(async ({ result }) => { + if (result instanceof Error) { + return; + } + const path = Utils.prepend(result.accessPaths.agnostic.client); const doc = Docs.Create.ImageDocument(path, { _nativeWidth: 200, _width: 200, title: name }); this.status = "getting user document"; @@ -75,12 +72,10 @@ class Uploader extends React.Component { pending.data = new List([doc]); } this.status = "finished"; + console.log("hi"); } - }); - - // console.log(window.location.origin + file[0]) - //imgPrev.setAttribute("src", window.location.origin + files[0].name) + }); } } } catch (error) { @@ -91,12 +86,12 @@ class Uploader extends React.Component { render() { return (
- + - + {/*
Upload
*/} -

{this.status}

-

{this.error}

+ {/*

{this.status}

+

{this.error}

*/}
); } @@ -104,25 +99,4 @@ class Uploader extends React.Component { } -// DocServer.init(window.location.protocol, window.location.hostname, resolvedPorts.socket, "image upload"); -(async () => { - const info = await CurrentUserUtils.loadCurrentUser(); - DocServer.init(window.location.protocol, window.location.hostname, resolvedPorts.socket, info.email + "mobile"); - await Docs.Prototypes.initialize(); - if (info.id !== "__guest__") { - // a guest will not have an id registered - await CurrentUserUtils.loadUserDocument(info); - } - document.getElementById('root')!.addEventListener('wheel', event => { - if (event.ctrlKey) { - event.preventDefault(); - } - }, true); - ReactDOM.render(( - // - - ), - document.getElementById('root') - ); -} -)(); \ No newline at end of file +// DocServer.init(window.location.protocol, window.location.hostname, 4321, "image upload"); -- cgit v1.2.3-70-g09d2 From 8d6fdb9460bd826c2be3a03cca9fa28a018b3e22 Mon Sep 17 00:00:00 2001 From: geireann <60007097+geireann@users.noreply.github.com> Date: Tue, 9 Jun 2020 22:06:14 +0800 Subject: adjust presentation view --- src/client/util/CurrentUserUtils.ts | 2 +- src/client/util/SettingsManager.scss | 4 +- src/client/views/nodes/PresBox.scss | 62 ++++++++++++++++++++-- .../views/presentationview/PresElementBox.scss | 48 ++++++++++++++--- src/mobile/ImageUpload.scss | 60 ++++++++++----------- src/mobile/ImageUpload.tsx | 1 + src/mobile/MobileInterface.tsx | 49 ++++++++++++++--- 7 files changed, 174 insertions(+), 52 deletions(-) (limited to 'src/mobile/ImageUpload.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 8ed275efc..3d38e7370 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -409,7 +409,7 @@ export class CurrentUserUtils { const docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, ischecked?: string, activePen?: Doc, backgroundColor?: string, dragFactory?: Doc }[] = [ { title: "library", icon: "bars", click: 'switchToLibrary()', backgroundColor: "lightgrey" }, { title: "record", icon: "microphone", click: 'openMobileAudio()', backgroundColor: "lightgrey" }, - { title: "upload", icon: "upload", click: 'uploadMobileImage()', backgroundColor: "lightgrey" }, + { title: "upload", icon: "upload", click: 'uploadImageMobile()', backgroundColor: "lightgrey" }, { title: "presentation", icon: "desktop", click: 'openMobilePresentation()', backgroundColor: "lightgrey" }, { title: "ink", icon: "pen-nib", backgroundColor: "lightgrey" }, { title: "settings", icon: "cog", click: 'openMobileSettings()', backgroundColor: "lightgrey" } diff --git a/src/client/util/SettingsManager.scss b/src/client/util/SettingsManager.scss index 6513cb223..eb1045f70 100644 --- a/src/client/util/SettingsManager.scss +++ b/src/client/util/SettingsManager.scss @@ -133,4 +133,6 @@ } -} \ No newline at end of file +} + +@media only screen and (max-width: 1000px) {} \ No newline at end of file diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index d48000e16..61641c989 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -16,6 +16,7 @@ height: calc(100% - 25px); width: 100%; } + .presBox-buttons { width: 100%; background: gray; @@ -24,6 +25,7 @@ display: grid; grid-column-end: 4; grid-column-start: 1; + .presBox-viewPicker { height: 25; position: relative; @@ -31,10 +33,12 @@ grid-column: 1/2; min-width: 15px; } + select { background: #323232; color: white; } + .presBox-button { margin-right: 2.5%; margin-left: 2.5%; @@ -44,10 +48,12 @@ align-items: center; background: #323232; color: white; + svg { margin: auto; } } + .collectionViewBaseChrome-viewPicker { min-width: 50; width: 5%; @@ -56,17 +62,65 @@ display: inline-block; } } - .presBox-backward, .presBox-forward { + + .presBox-backward, + .presBox-forward { width: 25px; border-radius: 5px; - top:50%; + top: 50%; position: absolute; display: inline-block; } + .presBox-backward { - left:5; + left: 5; } + .presBox-forward { - right:5; + right: 5; + } +} + +@media only screen and (max-width: 1000px) { .presBox-cont .presBox-buttons { + position: absolute; + top: 85%; + left: 50%; + transform: translate(-50%, 0); + width: max-content; + height: 15%; + z-index: 2; + align-items: center; + background: rgba(0, 0, 0, 0); + padding-top: 5px; + padding-bottom: 5px; + display: inline-flex; + } + + .presBox-cont .presBox-listCont { + position: absolute; + top: 50; + height: calc(100% - 80px); + width: 100%; + } + + .presBox-cont .presBox-buttons .presBox-button { + margin-right: 10px; + margin-left: 10px; + height: 130px; + width: 130px; + font-size: 50; + border-radius: 5px; + display: flex; + align-items: center; + background: #323232; + color: white; + } + + .presBox-cont .presBox-buttons .presBox-viewPicker { + height: 50; + width: 100; + font-size: 30px; + position: relative; + min-width: 50px; } } \ No newline at end of file diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/presentationview/PresElementBox.scss index ccd2e8947..1ddf3d8bc 100644 --- a/src/client/views/presentationview/PresElementBox.scss +++ b/src/client/views/presentationview/PresElementBox.scss @@ -13,9 +13,10 @@ -moz-user-select: none; -ms-user-select: none; user-select: none; - transition: all .1s; + transition: all .1s; padding: 0px; padding-bottom: 3px; + .documentView-node { position: absolute; z-index: 1; @@ -45,7 +46,7 @@ .presElementBox-closeIcon { border-radius: 20px; - transform:scale(0.7); + transform: scale(0.7); position: absolute; right: 0; top: 0; @@ -58,6 +59,7 @@ position: relative; width: 100%; height: auto; + .presElementBox-interaction { color: gray; float: left; @@ -65,6 +67,7 @@ width: 20px; height: 20px; } + .presElementBox-interaction-selected { color: white; float: left; @@ -90,15 +93,44 @@ display: flex; width: auto; justify-content: center; - margin:auto; + margin: auto; } .presElementBox-embeddedMask { - width:100%; - height:100%; + width: 100%; + height: 100%; position: absolute; - left:0; - top:0; + left: 0; + top: 0; background: transparent; - z-index:2; + z-index: 2; +} + +@media only screen and (max-width: 1000px) { + .presElementBox-buttons { + display: inline-flex; + position: relative; + width: 100%; + } + + .presElementBox-item { + display: inline-flex; + } + + .presElementBox-buttons .presElementBox-interaction { + color: gray; + float: left; + padding: 0px; + width: 50; + height: 40; + } + + .presElementBox-buttons .presElementBox-interaction-selected { + color: white; + float: left; + padding: 0px; + width: 50; + height: 50; + border: solid 1px darkgray; + } } \ No newline at end of file diff --git a/src/mobile/ImageUpload.scss b/src/mobile/ImageUpload.scss index 6ebf33438..afc4cc21e 100644 --- a/src/mobile/ImageUpload.scss +++ b/src/mobile/ImageUpload.scss @@ -1,12 +1,12 @@ @import "../client/views/globalCssVariables.scss"; .imgupload_cont { - // display: flex; - // justify-content: center; - // flex-direction: column; - // align-items: center; - // width: 100vw; - // height: 100vh; + display: flex; + justify-content: center; + flex-direction: column; + align-items: center; + width: 90vw; + height: 90vh; .upload_label { font-weight: normal !important; @@ -31,31 +31,31 @@ font-size: 3em; } - .input_file { - display: none; - } + // .input_file { + // display: none; + // } + + // // .upload_label, + // // .upload_button { + // // background: $dark-color; + // // font-size: 500%; + // // font-family: $sans-serif; + // // text-align: center; + // // padding: 5vh; + // // margin-bottom: 20px; + // // color: white; + // // } - // .upload_label, // .upload_button { - // background: $dark-color; - // font-size: 500%; - // font-family: $sans-serif; - // text-align: center; - // padding: 5vh; - // margin-bottom: 20px; - // color: white; + // width: 100%; + // padding: 13px 12px; + // border-bottom: 1px solid rgba(200, 200, 200, 0.7); + // font-family: Arial, Helvetica, sans-serif; + // font-style: normal; + // font-weight: normal; + // user-select: none; + // font-size: 35px; + // text-transform: uppercase; + // color: black; // } - - .upload_button { - width: 100%; - padding: 13px 12px; - border-bottom: 1px solid rgba(200, 200, 200, 0.7); - font-family: Arial, Helvetica, sans-serif; - font-style: normal; - font-weight: normal; - user-select: none; - font-size: 35px; - text-transform: uppercase; - color: black; - } } \ No newline at end of file diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index c35c4a917..8d7ccf450 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -12,6 +12,7 @@ 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'; export interface ImageUploadProps { Document: Doc; diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index c51b5b654..e2de7fed2 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -6,7 +6,7 @@ import { 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, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faHome, faLongArrowAltLeft, faBars, faTh, faChevronLeft + faThumbtack, faTree, faTv, faBook, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faHome, faLongArrowAltLeft, faBars, faTh, faChevronLeft } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable } from 'mobx'; @@ -43,7 +43,7 @@ library.add(faTasks, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTras 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, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faHome, faLongArrowAltLeft, faBars, faTh, faChevronLeft); + faThumbtack, faTree, faTv, faUndoAlt, faBook, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faHome, faLongArrowAltLeft, faBars, faTh, faChevronLeft); // @observer // export class MobileInterface extends React.Component { @@ -948,7 +948,8 @@ export class MobileInterface extends React.Component { @computed private get userDoc() { return Doc.UserDoc(); } @computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeMobile, Doc)) : CurrentUserUtils.GuestMobile; } // @computed private get activeContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeMobile, Doc)) : CurrentUserUtils.GuestMobile; } - @observable private mainDoc: any = CurrentUserUtils.setupMobileMenu(); + // Sets up new mobile menu only if activeMobile already exists + @observable private mainDoc: any = Doc.UserDoc().activeMobile !== undefined ? console.log("true") : CurrentUserUtils.setupMobileMenu(); @observable private renderView?: () => JSX.Element; @observable private audioState: any; @observable private activeToolbar: boolean = false; @@ -978,7 +979,7 @@ export class MobileInterface extends React.Component { componentDidMount = () => { library.add(...[faPenNib, faHighlighter, faEraser, faMousePointer, faThumbtack]); if (this.userDoc.activeMobile) { - console.log(Doc.UserDoc().activeMobile) + console.log(Doc.UserDoc().activeMobile); } if (this.userDoc && !this.mainContainer) { this.userDoc.activeMobile = this._homeDoc; @@ -1027,6 +1028,9 @@ export class MobileInterface extends React.Component { }); } + /** + * Handles the functionality to toggle the sidebar + */ toggleSidebar = () => { if (this._open === false) { this._open = true; @@ -1049,6 +1053,9 @@ export class MobileInterface extends React.Component { } } + /** + * Method called when 'Library' button is pressed + */ switchToLibrary = () => { this._parents.push(this._activeDoc); this.switchCurrentView((userDoc: Doc) => this._library); @@ -1057,6 +1064,9 @@ export class MobileInterface extends React.Component { this.toggleSidebar(); } + /** + * Back method for navigating within library + */ back = () => { let header = document.getElementById("header") as HTMLElement; let doc = Cast(this._parents.pop(), Doc) as Doc; @@ -1083,6 +1093,9 @@ export class MobileInterface extends React.Component { this._ink = false; } + /** + * Return 'Home", which implies returning to 'Home' buttons + */ returnHome = () => { if (this._homeMenu === false || this._open === true) { this._homeMenu = true; @@ -1096,6 +1109,9 @@ export class MobileInterface extends React.Component { } } + /** + * Return to primary Workspace in library (Workspaces Doc) + */ returnMain = () => { console.log("home"); this._parents = []; @@ -1108,6 +1124,9 @@ export class MobileInterface extends React.Component { // @computed get onChildClickHandler() { return ScriptCast(Doc.UserDoc.onClick); } + /** + * DocumentView for graphic display of all documents + */ displayWorkspaces = () => { if (this.mainContainer) { const backgroundColor = () => "white"; @@ -1174,9 +1193,13 @@ export class MobileInterface extends React.Component { } } - returnWidth = () => window.innerWidth; - returnHeight = () => (window.innerHeight - 300); + returnWidth = () => window.innerWidth; //The windows width + returnHeight = () => (window.innerHeight - 300); //Calculating the windows height (-300 to account for topbar) + /** + * Handles the click functionality in the library panel + * @param doc: doc for which the method is called + */ handleClick(doc: Doc) { let children = DocListCast(doc.data); if (doc.type !== "collection") { @@ -1311,6 +1334,7 @@ export class MobileInterface extends React.Component { // } } + // Handles when user clicks on document in the pathbar handlePathClick = (doc: Doc, index: number) => { if (doc === this._library) { this._activeDoc = doc; @@ -1709,7 +1733,6 @@ export class MobileInterface extends React.Component { const presentation = Cast(Doc.UserDoc().activePresentation, Doc) as Doc; if (presentation) { - console.log(this._activeDoc.mobile); console.log("presentation clicked: " + presentation.title); this._activeDoc = presentation; this.switchCurrentView((userDoc: Doc) => presentation); @@ -1748,7 +1771,6 @@ export class MobileInterface extends React.Component { {this.displayWorkspaces()} {this.renderDefaultContent()} - {/* */} {/* @@ -1767,14 +1789,25 @@ export class MobileInterface extends React.Component { ); } + + uploadImage = () => { + console.log("hello world of images"); + } } + + +const inputRef = React.createRef(); + + Scripting.addGlobal(function switchMobileView(doc: (userDoc: Doc) => Doc, renderView?: () => JSX.Element, onSwitch?: () => void) { return MobileInterface.Instance.switchCurrentView(doc, renderView, onSwitch); }); Scripting.addGlobal(function openMobilePresentation() { return MobileInterface.Instance.setupDefaultPresentation(); }); Scripting.addGlobal(function toggleMobileSidebar() { return MobileInterface.Instance.toggleSidebar(); }); Scripting.addGlobal(function openMobileAudio() { return MobileInterface.Instance.recordAudio(); }); Scripting.addGlobal(function openMobileSettings() { return SettingsManager.Instance.open(); }); Scripting.addGlobal(function switchToLibrary() { return MobileInterface.Instance.switchToLibrary(); }); +Scripting.addGlobal(function uploadImageMobile() { return MobileInterface.Instance.uploadImage(); }); + // WAS 2 -- cgit v1.2.3-70-g09d2 From bc80c711e7ab3044a0859c4b5d74e8e49cc5d077 Mon Sep 17 00:00:00 2001 From: geireann <60007097+geireann@users.noreply.github.com> Date: Wed, 10 Jun 2020 03:21:32 +0800 Subject: image upload functions w/ bugs - choose an image does not immediately update - close button does not move with rest of upload image --- src/client/util/CurrentUserUtils.ts | 7 +- src/client/util/SettingsManager.scss | 2 +- src/client/views/nodes/PresBox.scss | 43 ++----- .../views/presentationview/PresElementBox.scss | 51 +++++++- src/mobile/ImageUpload.scss | 138 +++++++++++++++------ src/mobile/ImageUpload.tsx | 74 ++++++++++- src/mobile/MobileInterface.tsx | 46 ++++++- 7 files changed, 273 insertions(+), 88 deletions(-) (limited to 'src/mobile/ImageUpload.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index d99d11c1f..563f8cfe4 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -430,7 +430,7 @@ export class CurrentUserUtils { } static setupMobileMenu() { - const menu = Cast(Docs.Create.StackingDocument(CurrentUserUtils.setupMobileButtons(), { + const menu = Cast(Docs.Create.StackingDocument(CurrentUserUtils.setupMobileButtons2(), { _width: 980, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled", title: "home", _autoHeight: true, _yMargin: 80 }), Doc) as Doc; return menu; @@ -647,7 +647,7 @@ export class CurrentUserUtils { const docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, ischecked?: string, activePen?: Doc, backgroundColor?: string, info: string, dragFactory?: Doc }[] = [ { title: "LIBRARY", icon: "bars", click: 'switchToLibrary()', backgroundColor: "#ffd6d6", info: "Navigate and access all of your documents within their respective collections" }, { title: "RECORD", icon: "microphone", click: 'openMobileAudio()', backgroundColor: "#ffbfbf", info: "Use your mobile to record audio and access it on Dash Web." }, - { title: "UPLOAD", icon: "upload", click: 'console.log("hi")', backgroundColor: "#ff9e9e", info: "Upload an image from your mobile device so it can be accessed on Dash Web" }, + { title: "UPLOAD", icon: "upload", click: 'uploadImageMobile()', backgroundColor: "#ff9e9e", info: "Upload an image from your mobile device so it can be accessed on Dash Web" }, { title: "PRESENTATION", icon: "desktop", click: 'openMobilePresentation()', backgroundColor: "#ff8080", info: "Use your phone as a remote for you presentation." }, // { title: "INK", icon: "pen-nib", backgroundColor: "lightgrey", info: "Doodle and draw with ink on your mobile and have it directly available on Dash Web" }, { title: "SETTINGS", icon: "cog", click: 'openMobileSettings()', backgroundColor: "#ff5e5e", info: "Change your password, log out, or manage your account security" } @@ -658,7 +658,7 @@ export class CurrentUserUtils { static mobileButton = (opts: DocumentOptions, docs: Doc[]) => new PrefetchProxy(Docs.Create.MulticolumnDocument(docs, { ...opts, dropAction: "alias", removeDropProperties: new List(["dropAction"]), _nativeWidth: 900, _nativeHeight: 250, _width: 900, _height: 250, _yMargin: 15, - borderRounding: "0", boxShadow: "0 0", _chromeStatus: "disabled", + borderRounding: "5px", boxShadow: "0 0", _chromeStatus: "disabled", })) as any as Doc static mobileTextContainer = (opts: DocumentOptions, docs: Doc[]) => new PrefetchProxy(Docs.Create.MultirowDocument(docs, { @@ -720,6 +720,7 @@ export class CurrentUserUtils { } } + static setupClickEditorTemplates(doc: Doc) { if (doc["clickFuncs-child"] === undefined) { const openInTarget = Docs.Create.ScriptingDocument(ScriptField.MakeScript( diff --git a/src/client/util/SettingsManager.scss b/src/client/util/SettingsManager.scss index 4d0fe5b8a..1eac9303b 100644 --- a/src/client/util/SettingsManager.scss +++ b/src/client/util/SettingsManager.scss @@ -140,7 +140,7 @@ background-color: whitesmoke !important; color: grey; width: 80vw; - height: 25vh; + height: 400px; } .settings-interface .settings-body .settings-content input { diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index 56c6b4357..2bb249ee4 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -84,7 +84,7 @@ @media only screen and (max-width: 1000px) { .presBox-cont .presBox-buttons { position: absolute; - top: 85%; + top: 70%; left: 50%; transform: translate(-50%, 0); width: max-content; @@ -107,10 +107,10 @@ .presBox-cont .presBox-buttons .presBox-button { margin-right: 10px; margin-left: 10px; - height: 130px; - width: 130px; - font-size: 50; - border-radius: 5px; + height: 250; + width: 250; + font-size: 70; + border-radius: 25px; display: flex; align-items: center; background: #323232; @@ -118,37 +118,12 @@ } .presBox-cont .presBox-buttons .presBox-viewPicker { + top: -70; + left: 2.5%; height: 50; - width: 100; - font-size: 30px; - position: relative; - min-width: 50px; - } - - .presElementBox-closeIcon { - border-radius: 20px; - transform: scale(2); - position: absolute; - right: 20; - top: 20; - padding: 8px; - } - - .presElementBox-buttons { - display: inline-flex; - position: absolute; - right: 0; - width: 50%; - } - - .presElementBox-name { + width: 95%; font-size: 30px; position: absolute; - display: inline-block; - top: 10px; - width: 50%; - text-overflow: ellipsis; - overflow: hidden; - white-space: pre; + min-width: 50px; } } \ No newline at end of file diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/presentationview/PresElementBox.scss index 1ddf3d8bc..ec82b0c51 100644 --- a/src/client/views/presentationview/PresElementBox.scss +++ b/src/client/views/presentationview/PresElementBox.scss @@ -122,7 +122,7 @@ float: left; padding: 0px; width: 50; - height: 40; + height: 50; } .presElementBox-buttons .presElementBox-interaction-selected { @@ -133,4 +133,53 @@ 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; + width: 50%; + } + + .presElementBox-name { + font-size: 30px; + position: absolute; + display: inline-block; + top: 10px; + 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; + } } \ No newline at end of file diff --git a/src/mobile/ImageUpload.scss b/src/mobile/ImageUpload.scss index afc4cc21e..6c782d4d8 100644 --- a/src/mobile/ImageUpload.scss +++ b/src/mobile/ImageUpload.scss @@ -5,21 +5,20 @@ justify-content: center; flex-direction: column; align-items: center; - width: 90vw; - height: 90vh; .upload_label { - font-weight: normal !important; + font-size: 3em; + font-weight: 700; + color: white; + background-color: black; + display: inline-block; + margin: 10; width: 100%; - padding: 13px 12px; - border-bottom: 1px solid rgba(200, 200, 200, 0.7); - font-family: Arial, Helvetica, sans-serif; - font-style: normal; - font-weight: normal; - user-select: none; - font-size: 35px; - text-transform: uppercase; - color: black; + border-radius: 10px; + } + + .upload_label:hover { + background-color: darkred; } .button_file { @@ -31,31 +30,92 @@ font-size: 3em; } - // .input_file { - // display: none; - // } - - // // .upload_label, - // // .upload_button { - // // background: $dark-color; - // // font-size: 500%; - // // font-family: $sans-serif; - // // text-align: center; - // // padding: 5vh; - // // margin-bottom: 20px; - // // color: white; - // // } - - // .upload_button { - // width: 100%; - // padding: 13px 12px; - // border-bottom: 1px solid rgba(200, 200, 200, 0.7); - // font-family: Arial, Helvetica, sans-serif; - // font-style: normal; - // font-weight: normal; - // user-select: none; - // font-size: 35px; - // text-transform: uppercase; - // color: black; - // } + .inputfile { + width: 0.1px; + height: 0.1px; + opacity: 0; + overflow: hidden; + position: absolute; + z-index: -1; + } + + .inputfile+label { + font-size: 3em; + font-weight: 700; + color: white; + background-color: black; + display: inline-block; + margin: 10px; + width: 100%; + border-radius: 10px; + } + + .inputfile:focus+label, + .inputfile+label:hover { + background-color: darkred; + } + +} + +.backgroundUpload { + height: 100vh; + top: 0; + z-index: 999; + width: 100vw; + position: absolute; + background-color: lightgrey; + opacity: 0.4; +} + +.image-upload { + top: 100%; + opacity: 0; +} + +.image-upload.active { + top: 0; + position: absolute; + z-index: 999; + height: 100vh; + width: 100vw; + opacity: 1; +} + +.uploadContainer { + top: 40; + position: absolute; + z-index: 1000; + height: 20vh; + width: 80vw; + opacity: 1; +} + +.closeUpload { + position: absolute; + border-radius: 10px; + top: 39.7%; + color: grey; + font-size: 40; + left: 65.8%; + z-index: 1002; + padding: 0px 3px; + background: aliceblue; + transition: 0.5s ease all; + border: 3px solid; + border-color: black; +} + +.loadingImage { + display: inline-flex; + width: max-content; +} + +.loadingSlab { + position: relative; + width: 30px; + height: 30px; + margin: 10; + border-radius: 20px; + opacity: 0.3; + background-color: black; } \ No newline at end of file diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index 8d7ccf450..df2beb85a 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -13,6 +13,7 @@ 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'; export interface ImageUploadProps { Document: Doc; @@ -35,6 +36,10 @@ export class Uploader extends React.Component { console.log("uploader click"); try { this.status = "initializing protos"; + const slab1 = document.getElementById("slab1"); + if (slab1) { + slab1.style.opacity = "1"; + } await Docs.Prototypes.initialize(); const imgPrev = document.getElementById("img_preview"); if (imgPrev) { @@ -44,8 +49,15 @@ export class Uploader extends React.Component { const name = files[0].name; const res = await Networking.UploadFilesToServer(files[0]); this.status = "uploading image"; + const slab2 = document.getElementById("slab2"); + if (slab2) { + slab2.style.opacity = "1"; + } this.status = "upload image, getting json"; - + const slab3 = document.getElementById("slab3"); + if (slab3) { + slab3.style.opacity = "1"; + } res.map(async ({ result }) => { if (result instanceof Error) { return; @@ -54,7 +66,15 @@ export class Uploader extends React.Component { const doc = Docs.Create.ImageDocument(path, { _nativeWidth: 200, _width: 200, title: name }); this.status = "getting user document"; - + const slab4 = document.getElementById("slab4"); + if (slab4) { + slab4.style.opacity = "1"; + } + this.status = "upload image, getting json"; + const slab5 = document.getElementById("slab5"); + if (slab5) { + slab5.style.opacity = "1"; + } const res = await rp.get(Utils.prepend("/getUserDocumentId")); if (!res) { throw new Error("No user id returned"); @@ -66,6 +86,10 @@ export class Uploader extends React.Component { } if (pending) { this.status = "has pending docs"; + const slab6 = document.getElementById("slab6"); + if (slab6) { + slab6.style.opacity = "1"; + } const data = await Cast(pending.data, listSpec(Doc)); if (data) { data.push(doc); @@ -74,6 +98,10 @@ export class Uploader extends React.Component { } this.status = "finished"; console.log("hi"); + const slab7 = document.getElementById("slab7"); + if (slab7) { + slab7.style.opacity = "1"; + } } }); @@ -84,19 +112,55 @@ export class Uploader extends React.Component { } } - render() { + // Updates label after a files is selected (so user knows a file is uploaded) + inputLabel = async () => { + const files: FileList | null = inputRef.current!.files; + await files; + var inputs = document.querySelectorAll('.inputFile'); + const label = document.getElementById("label"); + if (files && label) { + label.innerText = files[0].name; + } + } + + private get uploadInterface() { return (
- - + + +
Upload Image
{/*
Upload
*/} {/*

{this.status}

{this.error}

*/} +
+
+
+
+
+
+
+
+
); } + @observable private dialogueBoxOpacity = 1; + @observable private overlayOpacity = 0.4; + + render() { + return ( + + ); + } + } diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index d8ac7d1f1..c4b2ffbc1 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import { library } from '@fortawesome/fontawesome-svg-core'; import { - faTasks, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus, + faTasks, 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, @@ -26,6 +26,7 @@ import { InkingControl } from '../client/views/InkingControl'; import "./MobileInterface.scss"; import "./MobileMenu.scss"; import "./MobileHome.scss"; +import "./ImageUpload.scss"; import { DocumentManager } from '../client/util/DocumentManager'; import SettingsManager from '../client/util/SettingsManager'; import { Uploader } from "./ImageUpload"; @@ -38,7 +39,7 @@ import { SelectionManager } from "../client/util/SelectionManager"; import { SketchPicker } from "react-color"; import { ScriptField } from "../fields/ScriptField"; -library.add(faTasks, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus, +library.add(faTasks, 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, @@ -1240,7 +1241,7 @@ export class MobileInterface extends React.Component { // if (this._homeMenu == false) { let docArray = this.createPathname(); let items = docArray.map((doc: Doc, index: any) => { - if (index == 0) { + if (index === 0) { return (
{/* {this.menuOptions()} */} {/* {this.displayHome()} */} +
+ {this.uploadImage()} +
{this.pinToPresentation()} {this.downloadDocument()} @@ -1719,8 +1723,40 @@ export class MobileInterface extends React.Component { ); } + @observable private imageUploadActive: boolean = false; + + @action + toggleUpload = () => this.imageUploadActive = !this.imageUploadActive + + @action + closeUpload = () => { + this.imageUploadActive = false; + } + + // toggleUpload = () => { + // if (this.imageUploadActive === true) { + // this.imageUploadActive = false; + // } else { + // this.imageUploadActive = true; + // } + // } + uploadImage = () => { - console.log("hello world of images"); + if (this.imageUploadActive) { + console.log("active"); + } else if (!this.imageUploadActive) { + + } + console.log("upload"); + const workspaces = Cast(this.userDoc.myWorkspaces, Doc) as Doc; + return ( +
+
+ +
+ +
+ ); } } @@ -1735,7 +1771,7 @@ Scripting.addGlobal(function toggleMobileSidebar() { return MobileInterface.Inst Scripting.addGlobal(function openMobileAudio() { return MobileInterface.Instance.recordAudio(); }); Scripting.addGlobal(function openMobileSettings() { return SettingsManager.Instance.open(); }); Scripting.addGlobal(function switchToLibrary() { return MobileInterface.Instance.switchToLibrary(); }); -Scripting.addGlobal(function uploadImageMobile() { return MobileInterface.Instance.uploadImage(); }); +Scripting.addGlobal(function uploadImageMobile() { return MobileInterface.Instance.toggleUpload(); }); -- cgit v1.2.3-70-g09d2 From a37ca793caefc203071f082490097b6231b0daf8 Mon Sep 17 00:00:00 2001 From: Lionel Han <47760119+IGoByJoe@users.noreply.github.com> Date: Tue, 9 Jun 2020 21:25:26 -0700 Subject: fix some bugs in ImageUpload --- src/mobile/ImageUpload.tsx | 64 ++++++++++++++++++++++++++++++++++++++---- src/mobile/MobileInterface.tsx | 7 +++-- 2 files changed, 63 insertions(+), 8 deletions(-) (limited to 'src/mobile/ImageUpload.tsx') diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index df2beb85a..d5e7cec1b 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -5,7 +5,7 @@ import "./ImageUpload.scss"; import React = require('react'); import { DocServer } from '../client/DocServer'; import { observer } from 'mobx-react'; -import { observable } from 'mobx'; +import { observable, action } from 'mobx'; import { Utils } from '../Utils'; import { Networking } from '../client/Network'; import { Doc, Opt } from '../fields/Doc'; @@ -28,9 +28,10 @@ export interface ImageUploadProps { const inputRef = React.createRef(); @observer -export class Uploader extends React.Component { +export class Uploader extends React.Component { @observable error: string = ""; @observable status: string = ""; + @observable nm: string = "Choose an image"; onClick = async () => { console.log("uploader click"); @@ -102,14 +103,17 @@ export class Uploader extends React.Component { if (slab7) { slab7.style.opacity = "1"; } + setTimeout(this.clearUpload, 3000); } }); } + } } catch (error) { this.error = JSON.stringify(error); } + } // Updates label after a files is selected (so user knows a file is uploaded) @@ -118,16 +122,66 @@ export class Uploader extends React.Component { await files; var inputs = document.querySelectorAll('.inputFile'); const label = document.getElementById("label"); - if (files && label) { - label.innerText = files[0].name; + if (files && label && files.length !== 0) { + label.innerText = await files[0].name; + setTimeout(this.updateName, 1000); + } + } + + @action + updateName = () => { + const label = document.getElementById("label"); + if (label) { + this.nm = label.innerText; + + } + console.log("lol"); + } + + @action + clearUpload = () => { + const slab1 = document.getElementById("slab1"); + if (slab1) { + slab1.style.opacity = "0.4"; + } + const slab2 = document.getElementById("slab2"); + if (slab2) { + slab2.style.opacity = "0.4"; + } + const slab3 = document.getElementById("slab3"); + if (slab3) { + slab3.style.opacity = "0.4"; + } + const slab4 = document.getElementById("slab4"); + if (slab4) { + slab4.style.opacity = "0.4"; + } + const slab5 = document.getElementById("slab5"); + if (slab5) { + slab5.style.opacity = "0.4"; + } + const slab6 = document.getElementById("slab6"); + if (slab6) { + slab6.style.opacity = "0.4"; + } + const slab7 = document.getElementById("slab7"); + if (slab7) { + slab7.style.opacity = "0.4"; + } + + const label = document.getElementById("label"); + if (label) { + label.innerText = "Choose an image" + this.nm = "Choose an image"; } } + private get uploadInterface() { return (
- +
Upload Image
{/*
Upload
*/} diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index c4b2ffbc1..73dcabac8 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -955,6 +955,7 @@ export class MobileInterface extends React.Component { @observable private audioState: any; @observable private activeToolbar: boolean = false; @observable private sidebarActive: boolean = false; + @observable private imageUploadActive: boolean = false; public _activeDoc: Doc = this.mainDoc; public _homeDoc: Doc = this.mainDoc; @@ -1723,14 +1724,14 @@ export class MobileInterface extends React.Component { ); } - @observable private imageUploadActive: boolean = false; - @action toggleUpload = () => this.imageUploadActive = !this.imageUploadActive + @action closeUpload = () => { this.imageUploadActive = false; + console.log("1dude"); } // toggleUpload = () => { @@ -1754,7 +1755,7 @@ export class MobileInterface extends React.Component {
- +
); } -- cgit v1.2.3-70-g09d2 From 69fc5cff21c212a6eca9d125836844eea018fad0 Mon Sep 17 00:00:00 2001 From: Lionel Han <47760119+IGoByJoe@users.noreply.github.com> Date: Wed, 10 Jun 2020 00:24:07 -0700 Subject: functioning image upload --- src/mobile/ImageUpload.tsx | 35 +++++++++++++---------------------- src/mobile/MobileInterface.tsx | 2 -- 2 files changed, 13 insertions(+), 24 deletions(-) (limited to 'src/mobile/ImageUpload.tsx') diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index d5e7cec1b..504e4ceae 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -43,7 +43,9 @@ export class Uploader extends React.Component { } await Docs.Prototypes.initialize(); const imgPrev = document.getElementById("img_preview"); + console.log("buddy"); if (imgPrev) { + console.log("hi"); const files: FileList | null = inputRef.current!.files; if (files && files.length !== 0) { console.log(files[0]); @@ -103,12 +105,12 @@ export class Uploader extends React.Component { if (slab7) { slab7.style.opacity = "1"; } - setTimeout(this.clearUpload, 3000); + } }); } - + setTimeout(this.clearUpload, 3000); } } catch (error) { this.error = JSON.stringify(error); @@ -120,22 +122,10 @@ export class Uploader extends React.Component { inputLabel = async () => { const files: FileList | null = inputRef.current!.files; await files; - var inputs = document.querySelectorAll('.inputFile'); - const label = document.getElementById("label"); - if (files && label && files.length !== 0) { - label.innerText = await files[0].name; - setTimeout(this.updateName, 1000); - } - } - - @action - updateName = () => { - const label = document.getElementById("label"); - if (label) { - this.nm = label.innerText; - + if (files && files.length !== 0) { + console.log(files); + this.nm = files[0].name; } - console.log("lol"); } @action @@ -168,19 +158,20 @@ export class Uploader extends React.Component { if (slab7) { slab7.style.opacity = "0.4"; } + this.nm = "Choose an image"; - const label = document.getElementById("label"); - if (label) { - label.innerText = "Choose an image" - this.nm = "Choose an image"; + if (inputRef.current) { + inputRef.current.value = ""; } + console.log(inputRef.current!.files); } + private get uploadInterface() { return (
- +
Upload Image
{/*
Upload
*/} diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 73dcabac8..820a6885d 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -1731,7 +1731,6 @@ export class MobileInterface extends React.Component { @action closeUpload = () => { this.imageUploadActive = false; - console.log("1dude"); } // toggleUpload = () => { @@ -1749,7 +1748,6 @@ export class MobileInterface extends React.Component { } console.log("upload"); - const workspaces = Cast(this.userDoc.myWorkspaces, Doc) as Doc; return (
-- cgit v1.2.3-70-g09d2 From b13adb6e2620d80c019c7c8f6d344ba5ca2fcec2 Mon Sep 17 00:00:00 2001 From: Lionel Han <47760119+IGoByJoe@users.noreply.github.com> Date: Wed, 10 Jun 2020 22:43:35 -0700 Subject: finished up image upload and fixed bugs with pathbar and clicking workspaces twice --- src/client/views/GestureOverlay.tsx | 12 ++++++------ src/mobile/ImageUpload.scss | 12 ++++++++++++ src/mobile/ImageUpload.tsx | 11 +++++++++-- src/mobile/MobileInterface.tsx | 28 ++++++++++++++++++++-------- src/mobile/MobileMenu.scss | 1 + 5 files changed, 48 insertions(+), 16 deletions(-) (limited to 'src/mobile/ImageUpload.tsx') diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index a11c97b09..8cf2cdf55 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -115,12 +115,12 @@ export default class GestureOverlay extends Touchable { onReactTouchStart = (te: React.TouchEvent) => { document.removeEventListener("touchmove", this.onReactHoldTouchMove); document.removeEventListener("touchend", this.onReactHoldTouchEnd); - // if (RadialMenu.Instance._display === true) { - // te.preventDefault(); - // te.stopPropagation(); - // RadialMenu.Instance.closeMenu(); - // return; - // } + if (RadialMenu.Instance?._display === true) { + te.preventDefault(); + te.stopPropagation(); + RadialMenu.Instance.closeMenu(); + return; + } // this chunk adds new touch targets to a map of pointer events; this helps us keep track of individual fingers // so that we can know, for example, if two fingers are pinching out or in. diff --git a/src/mobile/ImageUpload.scss b/src/mobile/ImageUpload.scss index 6c782d4d8..d5ab31469 100644 --- a/src/mobile/ImageUpload.scss +++ b/src/mobile/ImageUpload.scss @@ -5,6 +5,7 @@ justify-content: center; flex-direction: column; align-items: center; + max-width: 400px; .upload_label { font-size: 3em; @@ -17,6 +18,13 @@ border-radius: 10px; } + .file { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + direction: ltr; + } + .upload_label:hover { background-color: darkred; } @@ -55,6 +63,10 @@ background-color: darkred; } + .status { + font-size: 2em; + } + } .backgroundUpload { diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index 504e4ceae..8f050aedd 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -32,6 +32,7 @@ export class Uploader extends React.Component { @observable error: string = ""; @observable status: string = ""; @observable nm: string = "Choose an image"; + @observable process: string = ""; onClick = async () => { console.log("uploader click"); @@ -48,6 +49,7 @@ export class Uploader extends React.Component { console.log("hi"); const files: FileList | null = inputRef.current!.files; if (files && files.length !== 0) { + this.process = "Uploading Image" console.log(files[0]); const name = files[0].name; const res = await Networking.UploadFilesToServer(files[0]); @@ -100,15 +102,18 @@ export class Uploader extends React.Component { pending.data = new List([doc]); } this.status = "finished"; + console.log("hi"); const slab7 = document.getElementById("slab7"); if (slab7) { slab7.style.opacity = "1"; } - + this.process = "Image Uploaded"; } }); + } else { + this.process = "No file selected"; } setTimeout(this.clearUpload, 3000); } @@ -163,6 +168,7 @@ export class Uploader extends React.Component { if (inputRef.current) { inputRef.current.value = ""; } + this.process = ""; console.log(inputRef.current!.files); } @@ -172,7 +178,7 @@ export class Uploader extends React.Component { return (
- +
Upload Image
{/*
Upload
*/} @@ -187,6 +193,7 @@ export class Uploader extends React.Component {
+

{this.process}

); } diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 820a6885d..0b5855e1f 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -1115,7 +1115,7 @@ export class MobileInterface extends React.Component { */ returnMain = () => { console.log("home"); - this._parents = []; + this._parents = [this._homeDoc]; // this.toggleSidebar(); this._activeDoc = this._library; this.switchCurrentView((userDoc: Doc) => this._library); @@ -1201,7 +1201,7 @@ export class MobileInterface extends React.Component { * Handles the click functionality in the library panel * @param doc: doc for which the method is called */ - handleClick(doc: Doc) { + handleClick = async (doc: Doc) => { let children = DocListCast(doc.data); if (doc.type !== "collection") { this._parents.push(this._activeDoc); @@ -1244,12 +1244,24 @@ export class MobileInterface extends React.Component { let items = docArray.map((doc: Doc, index: any) => { if (index === 0) { return ( -
-
this.handlePathClick(doc, index)}>{doc.title} -
-
); + <> + {this._homeMenu ? +
+
this.handlePathClick(doc, index)}>{doc.title} +
+
+ : +
+
this.handlePathClick(doc, index)}>{doc.title} +
+
} + ); + } else if (doc === this._activeDoc) { return (
diff --git a/src/mobile/MobileMenu.scss b/src/mobile/MobileMenu.scss index 669b55601..b98b51f31 100644 --- a/src/mobile/MobileMenu.scss +++ b/src/mobile/MobileMenu.scss @@ -309,6 +309,7 @@ body { text-align: center; user-select: none; z-index: 99; + pointer-events: none; } .toolbar { -- cgit v1.2.3-70-g09d2 From 87aa11c70be1ae0270c69adc0c1e0219f79ce820 Mon Sep 17 00:00:00 2001 From: geireann <60007097+geireann@users.noreply.github.com> Date: Tue, 16 Jun 2020 01:34:12 +0800 Subject: uploader + menu changes image upload w/ video and other files menu updates --- src/client/util/CurrentUserUtils.ts | 23 +-- src/client/views/GestureOverlay.scss | 2 +- .../views/collections/CollectionStackingView.scss | 10 +- .../collectionFreeForm/InkOptionsMenu.tsx | 4 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 2 +- .../views/presentationview/PresElementBox.tsx | 2 +- src/mobile/ImageUpload.scss | 1 + src/mobile/ImageUpload.tsx | 139 +++++++++--------- src/mobile/MobileInterface.tsx | 156 ++------------------- src/mobile/MobileMenu.scss | 8 +- 10 files changed, 109 insertions(+), 238 deletions(-) (limited to 'src/mobile/ImageUpload.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 1b0622f6d..e1605473c 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -329,7 +329,8 @@ export class CurrentUserUtils { doc.emptyWebpage = Docs.Create.WebDocument("", { title: "New Webpage", _nativeWidth: 850, _nativeHeight: 962, _width: 600, UseCors: true }); } if (doc.activeMobile === undefined) { - doc.activeMobile = CurrentUserUtils.setupMobileMenu(); + console.log("phone setup"); + this.setupActiveMobile(doc); } return [ { title: "Drag a comparison box", label: "Comp", icon: "columns", ignoreClick: true, drag: 'Docs.Create.ComparisonDocument()' }, @@ -398,16 +399,18 @@ export class CurrentUserUtils { return doc.myItemCreators as Doc; } - // static setupActiveMobile(doc: Doc) { - // if (doc.activeMobile === undefined) { - // doc.activeMobile = CurrentUserUtils.setupMobileMenu(); - // } - // } + static setupActiveMobile(doc: Doc) { + if (doc.activeMobile === undefined) { + console.log("undefined"); + doc.activeMobile = this.setupMobileMenu(); + } + return doc.activeMobile as Doc; + } static setupMobileMenu() { - const menu = Cast(Docs.Create.StackingDocument(CurrentUserUtils.setupMobileButtons(), { - _width: 980, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled", title: "home", _yMargin: 100 - }), Doc) as Doc; + const menu = new PrefetchProxy(Docs.Create.StackingDocument(this.setupMobileButtons(), { + _width: 980, ignoreClick: true, lockedPosition: false, _chromeStatus: "disabled", title: "home", _yMargin: 100 + })); return menu; } @@ -740,7 +743,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.setupActiveMobile(doc); + this.setupActiveMobile(doc); this.setupOverlays(doc); // documents in overlay layer this.setupDockedButtons(doc); // the bottom bar of font icons this.setupDefaultPresentation(doc); // presentation that's initially triggered diff --git a/src/client/views/GestureOverlay.scss b/src/client/views/GestureOverlay.scss index 107077792..f61f4a05e 100644 --- a/src/client/views/GestureOverlay.scss +++ b/src/client/views/GestureOverlay.scss @@ -1,7 +1,7 @@ .gestureOverlay-cont { width: 100vw; height: 100vh; - position: absolute; + position: fixed; top: 0; left: 0; touch-action: none; diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 714ff46a9..98efdfd23 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -428,11 +428,9 @@ .collectionStackingView .collectionStackingView-columnDragger, .collectionMasonryView .collectionStackingView-columnDragger { - width: 30; - transform: translate(0, -40px); - height: 30; - font-size: 40; - position: absolute; - margin-left: -5; + width: 0.1; + height: 0.1; + opacity: 0; + font-size: 0; } } \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx index 5a27f74e5..9f5e217bf 100644 --- a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx +++ b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx @@ -101,7 +101,7 @@ export default class InkOptionsMenu extends AntimodeMenu { title={`Draw ${btn}`} key={btn} onPointerDown={action(e => GestureOverlay.Instance.InkShape = btn)} - style={{ backgroundColor: btn === GestureOverlay.Instance.InkShape ? "121212" : "" }}> + style={{ backgroundColor: btn === GestureOverlay.Instance?.InkShape ? "121212" : "" }}> {this._icons[i]} )}, ; @@ -113,7 +113,7 @@ export default class InkOptionsMenu extends AntimodeMenu { title="Bezier changer" key="bezier" onPointerDown={e => this.changeBezier(e)} - style={ { backgroundColor:ActiveInkBezierApprox() ? "121212":"" } }> + style={{ backgroundColor: ActiveInkBezierApprox() ? "121212" : "" }}> B ; } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 1fab54d7e..e034e07a0 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1213,7 +1213,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : ""; const interactive = Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc.isBackground; if (this.props.isSelected()) { - this._editorView && RichTextMenu.Instance.updateFromDash(this._editorView, undefined, this.props); + this._editorView && RichTextMenu.Instance?.updateFromDash(this._editorView, undefined, this.props); } else if (FormattedTextBoxComment.textBox === this) { FormattedTextBoxComment.Hide(); } diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index caee06d8f..793d4068f 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -49,7 +49,7 @@ export class PresElementBox extends ViewBoxBaseComponent [this.rootDoc.presExpandInlineButton, this.collapsedHeight], - params => this.layoutDoc._height = NumCast(params[1]) + (Number(params[0]) ? 100 : 0), { fireImmediately: true }); + params => this.layoutDoc._height = NumCast(params[1]) + (Number(params[0]) ? 200 : 0), { fireImmediately: true }); } componentWillUnmount() { this._heightDisposer?.(); diff --git a/src/mobile/ImageUpload.scss b/src/mobile/ImageUpload.scss index d5ab31469..95c0c2680 100644 --- a/src/mobile/ImageUpload.scss +++ b/src/mobile/ImageUpload.scss @@ -6,6 +6,7 @@ flex-direction: column; align-items: center; max-width: 400px; + min-width: 400px; .upload_label { font-size: 3em; diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index 8f050aedd..3b4008e3f 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -14,6 +14,7 @@ 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'; export interface ImageUploadProps { Document: Doc; @@ -35,83 +36,80 @@ export class Uploader extends React.Component { @observable process: string = ""; onClick = async () => { - console.log("uploader click"); try { - this.status = "initializing protos"; + await Docs.Prototypes.initialize(); + const imgPrev = document.getElementById("img_preview"); const slab1 = document.getElementById("slab1"); if (slab1) { slab1.style.opacity = "1"; } - await Docs.Prototypes.initialize(); - const imgPrev = document.getElementById("img_preview"); - console.log("buddy"); if (imgPrev) { - console.log("hi"); const files: FileList | null = inputRef.current!.files; + const slab2 = document.getElementById("slab2"); + if (slab2) { + slab2.style.opacity = "1"; + } if (files && files.length !== 0) { - this.process = "Uploading Image" - console.log(files[0]); - const name = files[0].name; - const res = await Networking.UploadFilesToServer(files[0]); - this.status = "uploading image"; - const slab2 = document.getElementById("slab2"); - if (slab2) { - slab2.style.opacity = "1"; - } - this.status = "upload image, getting json"; - const slab3 = document.getElementById("slab3"); - if (slab3) { - slab3.style.opacity = "1"; - } - res.map(async ({ result }) => { - if (result instanceof Error) { - return; - } - const path = Utils.prepend(result.accessPaths.agnostic.client); - const doc = Docs.Create.ImageDocument(path, { _nativeWidth: 200, _width: 200, title: name }); - - this.status = "getting user document"; - const slab4 = document.getElementById("slab4"); - if (slab4) { - slab4.style.opacity = "1"; - } - this.status = "upload image, getting json"; - const slab5 = document.getElementById("slab5"); - if (slab5) { - slab5.style.opacity = "1"; + this.process = "Uploading Files"; + for (let index = 0; index < files.length; ++index) { + const file = files[index]; + const res = await Networking.UploadFilesToServer(file); + const slab3 = document.getElementById("slab3"); + if (slab3) { + slab3.style.opacity = "1"; } - const res = await rp.get(Utils.prepend("/getUserDocumentId")); - if (!res) { - throw new Error("No user id returned"); - } - const field = await DocServer.GetRefField(res); - let pending: Opt; - if (field instanceof Doc) { - pending = await Cast(field.rightSidebarCollection, Doc); - } - if (pending) { - this.status = "has pending docs"; - const slab6 = document.getElementById("slab6"); - if (slab6) { - slab6.style.opacity = "1"; + res.map(async ({ result }) => { + const name = file.name; + if (result instanceof Error) { + return; } - const data = await Cast(pending.data, listSpec(Doc)); - if (data) { - data.push(doc); + const path = Utils.prepend(result.accessPaths.agnostic.client); + let doc = null; + if (file.type === "video/mp4") { + doc = Docs.Create.VideoDocument(path, { _nativeWidth: 200, _width: 200, title: name }); } else { - pending.data = new List([doc]); + doc = Docs.Create.ImageDocument(path, { _nativeWidth: 200, _width: 200, title: name }); } - this.status = "finished"; - - console.log("hi"); - const slab7 = document.getElementById("slab7"); - if (slab7) { - slab7.style.opacity = "1"; + const slab4 = document.getElementById("slab4"); + if (slab4) { + slab4.style.opacity = "1"; + } + const res = await rp.get(Utils.prepend("/getUserDocumentId")); + if (!res) { + throw new Error("No user id returned"); + } + const field = await DocServer.GetRefField(res); + let pending: Opt; + if (field instanceof Doc) { + pending = await Cast(field.rightSidebarCollection, Doc); } - this.process = "Image Uploaded"; + if (pending) { + const data = await Cast(pending.data, listSpec(Doc)); + if (data) { + data.push(doc); + } else { + pending.data = new List([doc]); + } + this.status = "finished"; + const slab5 = document.getElementById("slab5"); + if (slab5) { + slab5.style.opacity = "1"; + } + this.process = "File " + (index + 1).toString() + " Uploaded"; + if (index === files.length) { + const slab6 = document.getElementById("slab6"); + if (slab6) { + slab6.style.opacity = "1"; + } + } + } + }); + this.process = "All Files Uploaded"; + const slab7 = document.getElementById("slab7"); + if (slab7) { + slab7.style.opacity = "1"; } - - }); + } } else { this.process = "No file selected"; } @@ -120,16 +118,18 @@ export class Uploader extends React.Component { } catch (error) { this.error = JSON.stringify(error); } - } // Updates label after a files is selected (so user knows a file is uploaded) inputLabel = async () => { const files: FileList | null = inputRef.current!.files; await files; - if (files && files.length !== 0) { + 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"; } } @@ -163,7 +163,7 @@ export class Uploader extends React.Component { if (slab7) { slab7.style.opacity = "0.4"; } - this.nm = "Choose an image"; + this.nm = "Choose files"; if (inputRef.current) { inputRef.current.value = ""; @@ -177,9 +177,12 @@ export class Uploader extends React.Component { private get uploadInterface() { return (
- + -
Upload Image
+
+ + Upload +
{/*
Upload
*/} {/*

{this.status}

diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index f2914eaae..211cc7a1a 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -52,10 +52,7 @@ export class MobileInterface extends React.Component { @observable static Instance: MobileInterface; @computed private get userDoc() { return Doc.UserDoc(); } @computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeMobile, Doc)) : CurrentUserUtils.GuestMobile; } - // @computed private get activeContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeMobile, Doc)) : CurrentUserUtils.GuestMobile; } - // Sets up new mobile menu only if activeMobile already exists - // @observable private mainDoc: any = this.userDoc.activeMobile === undefined ? CurrentUserUtils.setupMobileMenu() : this.userDoc.activeMobile; - @observable private mainDoc: any = CurrentUserUtils.setupMobileMenu(); + @observable private mainDoc: any = CurrentUserUtils.setupActiveMobile(this.userDoc); @observable private renderView?: () => JSX.Element; @observable private audioState: any; @observable private activeToolbar: boolean = false; @@ -86,13 +83,7 @@ export class MobileInterface extends React.Component { @action componentDidMount = () => { - library.add(...[faPenNib, faHighlighter, faEraser, faMousePointer, faThumbtack]); - if (this.userDoc.activeMobile) { - console.log(Doc.UserDoc().activeMobile); - } - if (this.userDoc && !this.mainContainer) { - this.userDoc.activeMobile = this._homeDoc; - } + Doc.UserDoc().activeMobile = this._homeDoc; this._homeDoc._viewType === "stacking" ? this.menuListView = true : this.menuListView = false; Doc.SetSelectedTool(InkTool.None); this.switchCurrentView((userDoc: Doc) => this._homeDoc); @@ -353,26 +344,6 @@ export class MobileInterface extends React.Component {
); } - // } - // } else { - - // return ( - //
- //
- //
- //
this.returnHome()}>Home - //
- //
- //
- //
- //
- // ); - // } - - // } } // Handles when user clicks on document in the pathbar @@ -393,16 +364,6 @@ export class MobileInterface extends React.Component { } renderDefaultContent = () => { - let menuButtons = DocListCast(this._homeDoc.data).map((doc: Doc, index: any) => { - if (doc.type !== "ink") { - return ( -
doc.onClick}>{doc.title} -
); - } - }); if (this._homeMenu === true) { return ( @@ -420,7 +381,10 @@ export class MobileInterface extends React.Component { {this.renderPathbar()}
@@ -429,7 +393,7 @@ export class MobileInterface extends React.Component { let workspaces = Cast(this.userDoc.myWorkspaces, Doc) as Doc; if (this._child) { - workspaces = this._child + workspaces = this._child; } let buttons = DocListCast(workspaces.data).map((doc: Doc, index: any) => { @@ -468,6 +432,10 @@ export class MobileInterface extends React.Component { : <> {buttons} +
ScriptField.MakeScript("createNewWorkspace()")}>Create New Workspace +
}
@@ -627,100 +595,12 @@ export class MobileInterface extends React.Component { // this.recordAudio(); } - // renderActiveCollection = (userDoc: Doc) => { - // if (this.activeContainer) { - // const active = Cast(this.activeContainer.data, listSpec(Doc)); - // if (active) { - // return ( - //
HELLO!
- // ); - // } - // } - // } - - onBack = (e: React.MouseEvent) => { - this.switchCurrentView((userDoc: Doc) => this.mainDoc); - Doc.SetSelectedTool(InkTool.None); // TODO: switch to previous tool - - DocServer.Mobile.dispatchOverlayTrigger({ - enableOverlay: false, - width: window.innerWidth, - height: window.innerHeight - }); - - // this.inkDoc = undefined; - this.drawingInk = false; - } - - shiftLeft = (e: React.MouseEvent) => { - DocServer.Mobile.dispatchOverlayPositionUpdate({ - dx: -10 - }); - e.preventDefault(); - e.stopPropagation(); - } - - shiftRight = (e: React.MouseEvent) => { - DocServer.Mobile.dispatchOverlayPositionUpdate({ - dx: 10 - }); - e.preventDefault(); - e.stopPropagation(); - } - panelHeight = () => window.innerHeight; panelWidth = () => window.innerWidth; //WAS 3 //WAS 1 - upload = async (e: React.MouseEvent) => { - if (this.mainContainer) { - const data = Cast(this.mainContainer.data, listSpec(Doc)); - if (data) { - const collectionDoc = await data[1]; //this should be the collection doc since the positions should be locked - const children = DocListCast(collectionDoc.data); - const uploadDoc = children.length === 1 ? children[0] : Docs.Create.StackingDocument(children, { - title: "Mobile Upload Collection", backgroundColor: "white", lockedPosition: true, _width: 300, _height: 300 - }); - if (uploadDoc) { - DocServer.Mobile.dispatchMobileDocumentUpload({ - docId: uploadDoc[Id], - }); - } - } - } - e.stopPropagation(); - e.preventDefault(); - } - - addWebToCollection = async () => { - let url = "https://en.wikipedia.org/wiki/Hedgehog"; - if (this.mainContainer) { - const data = Cast(this.mainContainer.data, listSpec(Doc)); - if (data) { - const webDoc = await data[0]; - const urlField: FieldResult = Cast(webDoc.data, WebField); - url = urlField ? urlField.url.toString() : "https://en.wikipedia.org/wiki/Hedgehog"; - - } - } - Docs.Create.WebDocument(url, { _width: 300, _height: 300, title: "Mobile Upload Web Doc" }); - } - - clearUpload = async () => { - if (this.mainContainer) { - const data = Cast(this.mainContainer.data, listSpec(Doc)); - if (data) { - const collectionDoc = await data[1]; - const children = DocListCast(collectionDoc.data); - children.forEach(doc => { - }); - // collectionDoc[data] = new List(); - } - } - } - pinToPresentation = () => { // Only making button available if it is an image if (this._activeDoc.type === "image") { @@ -845,7 +725,6 @@ export class MobileInterface extends React.Component { {this.uploadAudioButton()} {/* {this.colorTool()} */} {this.inkMenu()} -
{this.displayWorkspaces()} @@ -879,14 +758,6 @@ export class MobileInterface extends React.Component { this.imageUploadActive = false; } - // toggleUpload = () => { - // if (this.imageUploadActive === true) { - // this.imageUploadActive = false; - // } else { - // this.imageUploadActive = true; - // } - // } - uploadImage = () => { if (this.imageUploadActive) { console.log("active"); @@ -905,11 +776,6 @@ export class MobileInterface extends React.Component { } } - - -const inputRef = React.createRef(); - - Scripting.addGlobal(function switchMobileView(doc: (userDoc: Doc) => Doc, renderView?: () => JSX.Element, onSwitch?: () => void) { return MobileInterface.Instance.switchCurrentView(doc, renderView, onSwitch); }); Scripting.addGlobal(function openMobilePresentation() { return MobileInterface.Instance.setupDefaultPresentation(); }); Scripting.addGlobal(function toggleMobileSidebar() { return MobileInterface.Instance.toggleSidebar(); }); diff --git a/src/mobile/MobileMenu.scss b/src/mobile/MobileMenu.scss index da1e9d951..44d3acb6f 100644 --- a/src/mobile/MobileMenu.scss +++ b/src/mobile/MobileMenu.scss @@ -96,7 +96,7 @@ body { } .sidebar { - position: absolute; + position: fixed; top: 120px; opacity: 0; right: -100%; @@ -212,7 +212,7 @@ body { } .pathbar { - position: absolute; + position: fixed; top: 118px; left: 0px; background: #1a1a1a; @@ -373,7 +373,7 @@ body { } .homeSwitch { - position: absolute; + position: fixed; top: 212; right: 36px; display: inline-flex; @@ -401,4 +401,4 @@ body { .list.active { color: darkred; border-color: darkred; -} +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 3cb0b3aac05d9525d6deb4683328ce1309beee32 Mon Sep 17 00:00:00 2001 From: geireann <60007097+geireann@users.noreply.github.com> Date: Tue, 16 Jun 2020 02:06:33 +0800 Subject: image upload bug fixes --- src/mobile/ImageUpload.tsx | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'src/mobile/ImageUpload.tsx') diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index 3b4008e3f..fc26ba882 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -32,7 +32,7 @@ const inputRef = React.createRef(); export class Uploader extends React.Component { @observable error: string = ""; @observable status: string = ""; - @observable nm: string = "Choose an image"; + @observable nm: string = "Choose files"; @observable process: string = ""; onClick = async () => { @@ -96,19 +96,17 @@ export class Uploader extends React.Component { slab5.style.opacity = "1"; } this.process = "File " + (index + 1).toString() + " Uploaded"; - if (index === files.length) { - const slab6 = document.getElementById("slab6"); - if (slab6) { - slab6.style.opacity = "1"; - } + const slab6 = document.getElementById("slab6"); + if (slab6) { + slab6.style.opacity = "1"; } + const slab7 = document.getElementById("slab7"); + if (slab7) { + slab7.style.opacity = "1"; + } + } }); - this.process = "All Files Uploaded"; - const slab7 = document.getElementById("slab7"); - if (slab7) { - slab7.style.opacity = "1"; - } } } else { this.process = "No file selected"; @@ -180,7 +178,7 @@ export class Uploader extends React.Component {
- + Upload
{/*
Upload
*/} -- cgit v1.2.3-70-g09d2 From 22649d15932f719e0b57166158a3660941a7ef72 Mon Sep 17 00:00:00 2001 From: geireann <60007097+geireann@users.noreply.github.com> Date: Wed, 17 Jun 2020 18:38:20 +0800 Subject: pdf view updates --- deploy/mobile/image.html | 1 - src/client/views/nodes/PDFBox.scss | 391 ++++++++++++++------- src/client/views/nodes/PDFBox.tsx | 11 +- src/client/views/pdf/PDFViewer.tsx | 6 +- .../views/presentationview/PresElementBox.scss | 12 + src/mobile/ImageUpload.tsx | 2 +- 6 files changed, 292 insertions(+), 131 deletions(-) (limited to 'src/mobile/ImageUpload.tsx') diff --git a/deploy/mobile/image.html b/deploy/mobile/image.html index 718550f02..d30ad6ac2 100644 --- a/deploy/mobile/image.html +++ b/deploy/mobile/image.html @@ -3,7 +3,6 @@ Dash Mobile - diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index 6f18b1321..474587159 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -5,37 +5,38 @@ height: 100%; width: 100%; overflow: hidden; - cursor:auto; + cursor: auto; transform-origin: top left; z-index: 0; + .pdfBox-ui { position: absolute; - width: 100%; - height: 100%; - z-index: 1; - pointer-events: none; - - .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 { + width: 100%; + height: 100%; + z-index: 1; + pointer-events: none; + + .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; @@ -45,9 +46,10 @@ justify-content: center; border-radius: 3px; pointer-events: all; - } + } } - .pdfBox-overlayButton-fwd, + + .pdfBox-overlayButton-fwd, .pdfBox-overlayButton-back { background: #121721; height: 25px; @@ -61,15 +63,17 @@ position: absolute; top: 5; } + .pdfBox-overlayButton-fwd { left: 45; } + .pdfBox-overlayButton-back { left: 25; } - .pdfBox-nextIcon, - .pdfBox-prevIcon { + .pdfBox-nextIcon, + .pdfBox-prevIcon { background: #121721; height: 20px; width: 25px; @@ -80,96 +84,97 @@ border-radius: 3px; pointer-events: all; padding: 0px; - } - - .pdfBox-overlayButton:hover { - background: none; - } - - - .pdfBox-settingsCont { - position: absolute; - right: 0; - top: 3; - pointer-events: all; - - .pdfBox-settingsButton { - border-bottom-left-radius: 50%; - display: flex; - justify-content: space-evenly; - align-items: center; - height: 20px; - background: none; - padding: 0; - - .pdfBox-settingsButton-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-settingsButton-iconCont { - background: #121721; - height: 20px; - width: 25px; - display: flex; - justify-content: center; - align-items: center; - margin-left: -2px; - border-radius: 3px; - } - } - - .pdfBox-settingsButton:hover { - background: none; - } - - .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: 14px; - transition: all 0.5s; - - .pdfBox-settingsFlyout-title { - color: white; - } - - .pdfBox-settingsFlyout-kvpInput { - margin-top: 20px; - display: grid; - grid-template-columns: 47.5% 5% 47.5%; - } - } - } - - .pdfBox-overlayCont { - position: absolute; - width: calc(100% - 40px); - height: 20px; - background: #121721; - bottom: 0; - display: flex; - justify-content: center; - align-items: center; - overflow: hidden; - transition: left .5s; - pointer-events: all; - - .pdfBox-searchBar { - width: 70%; - font-size: 14px; - } - } + } + + .pdfBox-overlayButton:hover { + background: none; + } + + + .pdfBox-settingsCont { + position: absolute; + right: 0; + top: 3; + pointer-events: all; + + .pdfBox-settingsButton { + border-bottom-left-radius: 50%; + display: flex; + justify-content: space-evenly; + align-items: center; + height: 20px; + background: none; + padding: 0; + + .pdfBox-settingsButton-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-settingsButton-iconCont { + background: #121721; + height: 20px; + width: 25px; + display: flex; + justify-content: center; + align-items: center; + margin-left: -2px; + border-radius: 3px; + } + } + + .pdfBox-settingsButton:hover { + background: none; + } + + .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: 14px; + transition: all 0.5s; + + .pdfBox-settingsFlyout-title { + color: white; + } + + .pdfBox-settingsFlyout-kvpInput { + margin-top: 20px; + display: grid; + grid-template-columns: 47.5% 5% 47.5%; + } + } + } + + .pdfBox-overlayCont { + position: absolute; + width: calc(100% - 40px); + height: 20px; + background: #121721; + bottom: 0; + display: flex; + justify-content: center; + align-items: center; + overflow: hidden; + transition: left .5s; + pointer-events: all; + + .pdfBox-searchBar { + width: 70%; + font-size: 14px; + } + } } + .pdfBox-title-outer { width: 150%; height: 100%; @@ -178,9 +183,9 @@ z-index: 0; background: lightslategray; transform-origin: top left; - + .pdfBox-title { - color:lightgray; + color: lightgray; margin-top: auto; margin-bottom: auto; transform-origin: 42% 15%; @@ -209,6 +214,7 @@ .pdfBox-interactive { pointer-events: all; + .pdfViewer-text { .textLayer { span { @@ -216,4 +222,145 @@ } } } +} + +@media only screen and (max-width: 1000px) { + + .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 .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 .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; + } + + button.pdfBox-search { + font-size: 30px; + width: 50px; + height: 50px; + } + + .pdfBox .pdfBox-ui .pdfBox-nextIcon, + .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/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index fae216f17..78b7faeee 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -152,7 +152,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent e.stopPropagation()} style={{ left: `${this._searching ? 0 : 100}%` }}>
-
+
Annotation View Settings
@@ -215,10 +215,13 @@ export class PDFBox extends ViewBoxAnnotatableComponent 1000)); + console.log("_nativeHeight: " + this.Document._nativeHeight); + console.log("%: " + `${100 / this.contentScaling}%`); const classname = "pdfBox" + (this.active() ? "-interactive" : ""); return
1000) ? this.Document._nativeHeight || 0 : `${100 / this.contentScaling}%`, //Adjusted for mobile (!window.innerWidth < 1000) transform: `scale(${this.contentScaling})` }} >
@@ -230,7 +233,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent this._isChildActive; @computed get renderPdfView() { const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField); - return
+ return
1000) ? NumCast(this.Document._height) * this.props.PanelWidth() / NumCast(this.Document._width) : undefined }}> ; } @computed get pdfViewerDiv() { - return
; + return
; } @computed get contentScaling() { return this.props.ContentScaling(); } @computed get standinViews() { @@ -701,8 +701,8 @@ export class PDFViewer extends ViewBoxAnnotatableComponent 1000) ? NumCast(this.props.Document._nativeWidth) : `${100 / this.contentScaling}%`, + height: !this.props.Document._fitWidth && (window.innerWidth > 1000) ? NumCast(this.props.Document._nativeHeight) : `${100 / this.contentScaling}%`, transform: `scale(${this.props.ContentScaling()})` }} > {this.pdfViewerDiv} diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/presentationview/PresElementBox.scss index bf268eb8d..99fe2a3ba 100644 --- a/src/client/views/presentationview/PresElementBox.scss +++ b/src/client/views/presentationview/PresElementBox.scss @@ -115,6 +115,7 @@ .presElementBox-item { display: inline-flex; + overflow: hidden; } .presElementBox-buttons .presElementBox-interaction { @@ -148,6 +149,7 @@ position: absolute; top: 0; right: 0; + z-index: 3; width: 50%; } @@ -156,6 +158,7 @@ position: absolute; display: inline-block; top: 10px; + z-index: 3; width: 50%; text-overflow: ellipsis; overflow: hidden; @@ -182,4 +185,13 @@ 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/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index fc26ba882..d8b1913ee 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -179,7 +179,7 @@ export class Uploader extends React.Component {
- Upload +     Upload
{/*
Upload
*/} -- cgit v1.2.3-70-g09d2 From 57d4c562b6f0ef39dcd68f2985a56c4a683fcf49 Mon Sep 17 00:00:00 2001 From: geireann <60007097+geireann@users.noreply.github.com> Date: Thu, 18 Jun 2020 04:38:08 +0800 Subject: pdf changes + radial menu + create new workspaces (bug with ink) --- src/client/views/GestureOverlay.tsx | 8 --- .../views/collections/CollectionStackingView.tsx | 2 +- .../collectionFreeForm/InkOptionsMenu.tsx | 4 +- src/client/views/nodes/DocumentView.tsx | 12 ++-- src/client/views/nodes/PDFBox.scss | 2 +- src/client/views/nodes/PDFBox.tsx | 7 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 2 +- src/client/views/pdf/PDFViewer.tsx | 4 +- src/mobile/ImageUpload.tsx | 6 +- src/mobile/MobileInterface.tsx | 80 +++++++++++++++++++--- src/server/ApiManagers/PDFManager.ts | 3 +- 11 files changed, 94 insertions(+), 36 deletions(-) (limited to 'src/mobile/ImageUpload.tsx') diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index e51e2d4e1..1c305ebeb 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -575,14 +575,6 @@ export default class GestureOverlay extends Touchable { const points = this._points.map(p => ({ X: p.X - B.left, Y: p.Y - B.top })); //push first points to so interactionUtil knows pointer is up this._points.push({ X: this._points[0].X, Y: this._points[0].Y }); - if (MobileInterface.Instance && MobileInterface.Instance.drawingInk) { - DocServer.Mobile.dispatchGesturePoints({ - points: this._points, - bounds: B, - color: ActiveInkColor(), - width: ActiveInkWidth() - }); - } const initialPoint = this._points[0.]; const xInGlass = initialPoint.X > (this._thumbX ?? Number.MAX_SAFE_INTEGER) && initialPoint.X < (this._thumbX ?? Number.MAX_SAFE_INTEGER) + (this.height); diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 797aabf18..9f1b5d63c 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -476,7 +476,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) transformOrigin: "top left", }} onScroll={action(e => { - if (!this.props.isSelected() && this.props.renderDepth && window.innerWidth > 1000) e.currentTarget.scrollTop = this._scroll; + if (!this.props.isSelected() && this.props.renderDepth && window.screen.width > 600) e.currentTarget.scrollTop = this._scroll; else this._scroll = e.currentTarget.scrollTop; })} onDrop={this.onExternalDrop.bind(this)} diff --git a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx index 647847b68..676dc10f4 100644 --- a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx +++ b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx @@ -130,13 +130,13 @@ export default class InkOptionsMenu extends AntimodeMenu { ]; const mobileButtons = [ - this.shapeButtons, + ...this.shapeButtons, this.bezierButton, this.widthPicker, this.colorPicker, ]; - return (window.innerWidth < 1000 ? this.getElement(mobileButtons) : this.getElement(buttons)); + return (window.screen.width < 600 ? this.getElement(mobileButtons) : this.getElement(buttons)); } } Scripting.addGlobal(function activatePen(penBtn: any) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 75627607b..e027b6a0f 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -31,7 +31,7 @@ import { SelectionManager } from "../../util/SelectionManager"; import SharingManager from '../../util/SharingManager'; import { Transform } from "../../util/Transform"; import { undoBatch, UndoManager } from "../../util/UndoManager"; -import { CollectionDockingView } from "../collections/CollectionDockingView"; +import { CollectionDockingView, DockedFrameRenderer } from "../collections/CollectionDockingView"; import { CollectionView, CollectionViewType } from '../collections/CollectionView'; import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from '../ContextMenuItem'; @@ -43,6 +43,7 @@ import "./DocumentView.scss"; import { LinkAnchorBox } from './LinkAnchorBox'; import { RadialMenu } from './RadialMenu'; import React = require("react"); +import { MobileInterface } from '../../../mobile/MobileInterface'; library.add(fa.faEdit, fa.faTrash, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faCompressArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faAlignCenter, fa.faCaretSquareRight, fa.faSquare, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faLink, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock, fa.faLock, fa.faLaptopCode, fa.faMale, @@ -181,10 +182,11 @@ export class DocumentView extends DocComponent(Docu const pt = me.touchEvent.touches[me.touchEvent.touches.length - 1]; RadialMenu.Instance.openMenu(pt.pageX - 15, pt.pageY - 15); - RadialMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "map-pin", selected: -1 }); - RadialMenu.Instance.addItem({ description: "Delete this document", event: () => { this.props.ContainingCollectionView?.removeDocument(this.props.Document), RadialMenu.Instance.closeMenu(); }, icon: "layer-group", selected: -1 }); - RadialMenu.Instance.addItem({ description: "Open in a new tab", event: () => this.props.addDocTab(this.props.Document, "onRight"), icon: "trash", selected: -1 }); - RadialMenu.Instance.addItem({ description: "Pin to Presentation", event: () => this.props.pinToPres(this.props.Document), icon: "folder", selected: -1 }); + // RadialMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "map-pin", selected: -1 }); + RadialMenu.Instance.addItem({ description: "Delete", event: () => { this.props.ContainingCollectionView?.removeDocument(this.props.Document), RadialMenu.Instance.closeMenu(); }, icon: "external-link-square-alt", selected: -1 }); + // RadialMenu.Instance.addItem({ description: "Open in a new tab", event: () => this.props.addDocTab(this.props.Document, "onRight"), icon: "trash", selected: -1 }); + RadialMenu.Instance.addItem({ description: "Pin", event: () => DockedFrameRenderer.PinDoc(this.props.Document), icon: "map-pin", selected: -1 }); + RadialMenu.Instance.addItem({ description: "Open", event: () => MobileInterface.Instance.handleClick(this.props.Document), icon: "trash", selected: -1 }); SelectionManager.DeselectAll(); } diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index 474587159..1a31d2916 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -224,7 +224,7 @@ } } -@media only screen and (max-width: 1000px) { +@media only screen and (max-width: 600px) { .pdfBox .pdfBox-ui .pdfBox-settingsCont .pdfBox-settingsButton, .pdfBox-interactive .pdfBox-ui .pdfBox-settingsCont .pdfBox-settingsButton { diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 78b7faeee..4b4348d3c 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -215,13 +215,14 @@ export class PDFBox extends ViewBoxAnnotatableComponent 1000)); + console.log("fitWidth ?: " + !(this.props.Document._fitWidth) && (window.screen.width > 600)); console.log("_nativeHeight: " + this.Document._nativeHeight); console.log("%: " + `${100 / this.contentScaling}%`); const classname = "pdfBox" + (this.active() ? "-interactive" : ""); return
1000) ? this.Document._nativeHeight || 0 : `${100 / this.contentScaling}%`, //Adjusted for mobile (!window.innerWidth < 1000) + //height adjusted for mobile (window.screen.width > 600) + height: !this.props.Document._fitWidth && (window.screen.width > 600) ? this.Document._nativeHeight || 0 : `${100 / this.contentScaling}%`, transform: `scale(${this.contentScaling})` }} >
@@ -233,7 +234,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent this._isChildActive; @computed get renderPdfView() { const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField); - return
1000) ? NumCast(this.Document._height) * this.props.PanelWidth() / NumCast(this.Document._width) : undefined }}> + return
600) ? NumCast(this.Document._height) * this.props.PanelWidth() / NumCast(this.Document._width) : undefined }}> { - if (window.innerWidth < 1000) null; + if (window.screen.width < 600) null; else if (this._editorView && (this._editorView as any).docView) { const mark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight); const activeMark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight, { selected: true }); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 9cdbea2da..57b7bceca 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -709,8 +709,8 @@ export class PDFViewer extends ViewBoxAnnotatableComponent 1000) ? NumCast(this.props.Document._nativeWidth) : `${100 / this.contentScaling}%`, - height: !this.props.Document._fitWidth && (window.innerWidth > 1000) ? NumCast(this.props.Document._nativeHeight) : `${100 / this.contentScaling}%`, + width: !this.props.Document._fitWidth && (window.screen.width > 600) ? NumCast(this.props.Document._nativeWidth) : `${100 / this.contentScaling}%`, + height: !this.props.Document._fitWidth && (window.screen.width > 600) ? NumCast(this.props.Document._nativeHeight) : `${100 / this.contentScaling}%`, transform: `scale(${this.props.ContentScaling()})` }} > {this.pdfViewerDiv} diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index d8b1913ee..b66f0461d 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -65,8 +65,11 @@ export class Uploader extends React.Component { } const path = Utils.prepend(result.accessPaths.agnostic.client); let doc = null; + console.log("type: " + file.type); if (file.type === "video/mp4") { doc = Docs.Create.VideoDocument(path, { _nativeWidth: 200, _width: 200, title: name }); + } else if (file.type === "application/pdf") { + doc = Docs.Create.PdfDocument(path, { _width: 200, title: name }); } else { doc = Docs.Create.ImageDocument(path, { _nativeWidth: 200, _width: 200, title: name }); } @@ -175,7 +178,7 @@ export class Uploader extends React.Component { private get uploadInterface() { return (
- +
@@ -217,4 +220,3 @@ export class Uploader extends React.Component { } -// DocServer.init(window.location.protocol, window.location.hostname, 4321, "image upload"); diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 5acdc1dea..644535179 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import { library } from '@fortawesome/fontawesome-svg-core'; import { - faTasks, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus, + faTasks, 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, @@ -17,7 +17,7 @@ import { FieldValue, Cast } from '../fields/Types'; import { CurrentUserUtils } from '../client/util/CurrentUserUtils'; import { emptyPath, emptyFunction, returnFalse, returnOne, returnTrue, returnZero, Utils } from '../Utils'; import { DocServer } from '../client/DocServer'; -import { Docs } from '../client/documents/Documents'; +import { 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'; @@ -36,8 +36,11 @@ 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 } from "../client/util/UndoManager"; +import { MainView } from "../client/views/MainView"; +import { List } from "../fields/List"; -library.add(faTasks, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus, +library.add(faTasks, 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, @@ -149,7 +152,7 @@ export class MobileInterface extends React.Component { * Return 'Home", which implies returning to 'Home' buttons */ returnHome = () => { - if (this._homeMenu === false || this.sidebarActive === true) { + if (this._homeMenu || this.sidebarActive) { this._homeMenu = true; this._parents = []; this._activeDoc = this._homeDoc; @@ -220,7 +223,7 @@ export class MobileInterface extends React.Component { */ handleClick = async (doc: Doc) => { const children = DocListCast(doc.data); - if (doc.type !== "collection") { + if (doc.type !== "collection" && this.sidebarActive) { this._parents.push(this._activeDoc); this._activeDoc = doc; this.switchCurrentView((userDoc: Doc) => doc); @@ -333,7 +336,7 @@ export class MobileInterface extends React.Component { // Renders the contents of the menu and sidebar renderDefaultContent = () => { - if (this._homeMenu === true) { + if (this._homeMenu) { return (
@@ -351,7 +354,7 @@ export class MobileInterface extends React.Component {
ScriptField.MakeScript("createNewWorkspace()")}>Create New Workspace + onClick={() => MainView.Instance?.createNewWorkspace()}>Create New Workspace
@@ -403,7 +406,10 @@ export class MobileInterface extends React.Component { {buttons}
ScriptField.MakeScript("createNewWorkspace()")}>Create New Workspace + style={{ opacity: 0.7 }} + onClick={() => this.createNewWorkspace()}> + +
Create New Workspace
} @@ -413,6 +419,32 @@ export class MobileInterface extends React.Component { ); } + /** + * Handles the Create New Workspace button in the menu + */ + @action + createNewWorkspace = async (id?: string) => { + const workspaces = Cast(this.userDoc.myWorkspaces, Doc) as Doc; + const workspaceCount = DocListCast(workspaces.data).length + 1; + const freeformOptions: DocumentOptions = { + x: 0, + y: 400, + title: "Collection " + workspaceCount, + _LODdisable: true + }; + 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([toggleTheme!, toggleComic!, cloneWorkspace!]); + workspaceDoc.contextMenuLabels = new List(["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) => { e.stopPropagation(); } @@ -431,7 +463,7 @@ export class MobileInterface extends React.Component { } } - // Button for switching between pan and ink mode + // Button for switching between pen and ink mode @action onSwitchInking = () => { const button = document.getElementById("inkButton") as HTMLElement; @@ -465,6 +497,16 @@ export class MobileInterface extends React.Component { if (this._activeDoc._viewType === "docking") { return ( <> + {/*
{ + UndoManager.Undo(); + e.stopPropagation(); + }}> + +
*/}
+ {/*
{ + UndoManager.Redo(); + e.stopPropagation(); + }}> + +
*/} ); } } @@ -645,6 +697,12 @@ export class MobileInterface extends React.Component { ); } + displayRadialMenu = () => { + if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc) { + return ; + } + } + onDragOver = (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); @@ -669,12 +727,14 @@ export class MobileInterface extends React.Component { {this.displayWorkspaces()} {this.renderDefaultContent()} - + {this.displayRadialMenu()}
); } } + + Scripting.addGlobal(function switchMobileView(doc: (userDoc: Doc) => Doc, renderView?: () => JSX.Element, onSwitch?: () => void) { return MobileInterface.Instance.switchCurrentView(doc, renderView, onSwitch); }); Scripting.addGlobal(function openMobilePresentation() { return MobileInterface.Instance.setupDefaultPresentation(); }); Scripting.addGlobal(function toggleMobileSidebar() { return MobileInterface.Instance.toggleSidebar(); }); diff --git a/src/server/ApiManagers/PDFManager.ts b/src/server/ApiManagers/PDFManager.ts index d2a9e9cce..b0b5a484a 100644 --- a/src/server/ApiManagers/PDFManager.ts +++ b/src/server/ApiManagers/PDFManager.ts @@ -55,7 +55,8 @@ async function CreateThumbnail(coreFilename: string, pageNum: number, res: expre const documentProxy = await Pdfjs.getDocument(sourcePath).promise; const factory = new NodeCanvasFactory(); const page = await documentProxy.getPage(pageNum); - const viewport = page.getViewport(1 as any); + const scale = 1; + const viewport = page.getViewport(scale as any); const { canvas, context } = factory.create(viewport.width, viewport.height); const renderContext = { canvasContext: context, -- cgit v1.2.3-70-g09d2 From a19d891f386816f127ea1ee3970c6ec48adb0d74 Mon Sep 17 00:00:00 2001 From: Lionel Han <47760119+IGoByJoe@users.noreply.github.com> Date: Thu, 18 Jun 2020 22:01:02 -0700 Subject: added mobile collection to menu and added image upload to current collection --- src/client/util/CurrentUserUtils.ts | 1 + src/mobile/ImageUpload.tsx | 9 +++++-- src/mobile/MobileInterface.tsx | 48 ++++++++++++++++++++++++++++++++++--- 3 files changed, 53 insertions(+), 5 deletions(-) (limited to 'src/mobile/ImageUpload.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 7b867ed02..b7da4ae2f 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -469,6 +469,7 @@ export class CurrentUserUtils { { title: "RECORD", icon: "microphone", click: 'openMobileAudio()', backgroundColor: "#ffbfbf", info: "Use your phone to record and upload audio onto Dash Web." }, { title: "UPLOAD", icon: "upload", click: 'uploadImageMobile()', backgroundColor: "#ff9e9e", info: "Upload images or videos from your mobile device so they can be accessed on Dash Web." }, { title: "PRESENTATION", icon: "desktop", click: 'openMobilePresentation()', backgroundColor: "#ff8080", info: "Use your phone as a remote for you presentation." }, + { title: "MOBILE UPLOAD", icon: "mobile", click: 'switchToMobileUploads()', backgroundColor: "#ff7373", info: "Access the collection of your mobile uploads." }, { title: "SETTINGS", icon: "cog", click: 'openMobileSettings()', backgroundColor: "#ff5e5e", info: "Change your password, log out, or manage your account security." } ]; return docProtoData.filter(d => !buttons || !buttons.includes(d.title)).map(data => diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index b66f0461d..0b63c42be 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -29,7 +29,7 @@ export interface ImageUploadProps { const inputRef = React.createRef(); @observer -export class Uploader extends React.Component { +export class Uploader extends React.Component { @observable error: string = ""; @observable status: string = ""; @observable nm: string = "Choose files"; @@ -37,6 +37,7 @@ export class Uploader extends React.Component { onClick = async () => { try { + const col = this.props.Document; await Docs.Prototypes.initialize(); const imgPrev = document.getElementById("img_preview"); const slab1 = document.getElementById("slab1"); @@ -84,7 +85,11 @@ export class Uploader extends React.Component { const field = await DocServer.GetRefField(res); let pending: Opt; if (field instanceof Doc) { - pending = await Cast(field.rightSidebarCollection, 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)); diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 3a81e5de1..2fde359aa 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -674,6 +674,15 @@ export class MobileInterface extends React.Component { @action toggleUpload = () => this.imageUploadActive = !this.imageUploadActive + @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; + } + // For closing the image upload pop up @action closeUpload = () => { @@ -687,12 +696,22 @@ export class MobileInterface extends React.Component { } else if (!this.imageUploadActive) { } + + let doc; + let toggle; + if (this._homeMenu === false) { + doc = this._activeDoc; + toggle = this.toggleUploadInCollection; + } else { + doc = Cast(Doc.UserDoc().rightSidebarCollection, Doc) as Doc + toggle = this.toggleUpload; + } return (
-
+
- +
); } @@ -708,8 +727,27 @@ export class MobileInterface extends React.Component { e.stopPropagation(); } - uploadToCurrentCollection = (doc: Doc) => { + uploadImageButton = () => { + if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc && this._activeDoc._viewType !== "docking" && this._activeDoc.title !== "WORKSPACES") { + return
+ +
+ } + } + switchToMobileUploads = () => { + if (this._activeDoc.title !== "Presentation") { + this._parents.push(this._activeDoc); + } + const mobileUpload = Cast(Doc.UserDoc().rightSidebarCollection, Doc) as Doc; + console.log(mobileUpload.title); + this._activeDoc = mobileUpload; + this.switchCurrentView((userDoc: Doc) => mobileUpload); + this._homeMenu = false; } render() { @@ -718,14 +756,17 @@ export class MobileInterface extends React.Component {
{this.uploadImage()} +
{this.switchMenuView()} {this.inkMenu()}
+ {this.uploadImageButton()} {this.pinToPresentation()} {this.downloadDocument()} {this.drawInk()} {this.uploadAudioButton()} +
{this.displayWorkspaces()} @@ -746,3 +787,4 @@ Scripting.addGlobal(function openMobileAudio() { return MobileInterface.Instance Scripting.addGlobal(function openMobileSettings() { return SettingsManager.Instance.open(); }); Scripting.addGlobal(function switchToLibrary() { return MobileInterface.Instance.switchToLibrary(); }); Scripting.addGlobal(function uploadImageMobile() { return MobileInterface.Instance.toggleUpload(); }); +Scripting.addGlobal(function switchToMobileUploads() { return MobileInterface.Instance.switchToMobileUploads(); }); -- cgit v1.2.3-70-g09d2 From 10754a14c8d0dda68f2484e523f6901b3e7daee3 Mon Sep 17 00:00:00 2001 From: geireann <60007097+geireann@users.noreply.github.com> Date: Fri, 19 Jun 2020 14:14:28 +0800 Subject: css changes and bug fixes Presentation Undo / Redo Image upload Record Audio --- src/client/views/collections/CollectionView.tsx | 2 +- .../views/collections/CollectionViewChromes.scss | 6 + .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/AudioBox.tsx | 2 +- src/client/views/nodes/PresBox.scss | 10 +- src/mobile/AudioUpload.scss | 119 +++++++++++ src/mobile/AudioUpload.tsx | 237 +++++++++++++++++++++ src/mobile/ImageUpload.scss | 15 +- src/mobile/ImageUpload.tsx | 58 +++-- src/mobile/MobileInterface.tsx | 205 ++++++++++-------- src/mobile/MobileMenu.scss | 15 +- 11 files changed, 531 insertions(+), 140 deletions(-) create mode 100644 src/mobile/AudioUpload.scss create mode 100644 src/mobile/AudioUpload.tsx (limited to 'src/mobile/ImageUpload.tsx') diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index a700d0dfb..7c5c87e3e 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -283,7 +283,7 @@ export class CollectionView extends Touchable ImageUtils.ExportHierarchyToFileSystem(this.props.Document) }); !more && ContextMenu.Instance.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" }); diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss index f85cbfee2..54ee4ab3b 100644 --- a/src/client/views/collections/CollectionViewChromes.scss +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -80,6 +80,12 @@ // margin-top: 10px; } + @media only screen and (max-width: 1000) { + .collectionViewBaseChrome-collapse { + display: none; + } + } + .collectionViewBaseChrome-template, .collectionViewBaseChrome-viewModes { display: grid; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 82d6dee73..327e172bb 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1199,7 +1199,7 @@ export class CollectionFreeFormView extends CollectionSubView { if (this.props.annotationsKey) return; - ContextMenu.Instance.addItem({ + ContextMenu.Instance?.addItem({ description: (this._timelineVisible ? "Close" : "Open") + " Animation Timeline", event: action(() => { this._timelineVisible = !this._timelineVisible; }), icon: this._timelineVisible ? faEyeSlash : faEye diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 2e0be1c6a..cb0582d87 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -161,7 +161,7 @@ export class AudioBox extends ViewBoxBaseComponent this.layoutDoc.playOnSelect = !this.layoutDoc.playOnSelect, icon: "expand-arrows-alt" }); - ContextMenu.Instance.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" }); + ContextMenu.Instance?.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" }); } stopRecording = action(() => { diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index ccce6e627..e62aa48fb 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -105,15 +105,13 @@ } .presBox-cont .presBox-buttons .presBox-button { - margin-right: 10px; - margin-left: 10px; + margin-top: 5%; height: 250; - width: 250; - font-size: 70; - border-radius: 25px; + width: 300; + font-size: 100; display: flex; align-items: center; - background: #323232; + background: 323232; color: white; } diff --git a/src/mobile/AudioUpload.scss b/src/mobile/AudioUpload.scss new file mode 100644 index 000000000..5f0ba465a --- /dev/null +++ b/src/mobile/AudioUpload.scss @@ -0,0 +1,119 @@ +@import "../client/views/globalCssVariables.scss"; + +.audioUpload_cont { + display: flex; + justify-content: center; + flex-direction: column; + align-items: center; + max-width: 400px; + min-width: 400px; + + .upload_label { + font-size: 3em; + font-weight: 700; + color: white; + background-color: black; + display: inline-block; + margin: 10; + width: 100%; + border-radius: 10px; + } + + .file { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + direction: ltr; + } + + .upload_label:hover { + background-color: darkred; + } + + .button_file { + text-align: center; + height: 50%; + width: 50%; + background-color: paleturquoise; + color: grey; + font-size: 3em; + } + + .inputfile { + width: 0.1px; + height: 0.1px; + opacity: 0; + overflow: hidden; + position: absolute; + z-index: -1; + } + + .inputfile+label { + font-size: 3em; + font-weight: 700; + color: white; + background-color: black; + display: inline-block; + margin: 10px; + width: 100%; + border-radius: 10px; + } + + .inputfile:focus+label, + .inputfile+label:hover { + background-color: darkred; + } + + .status { + font-size: 2em; + } + +} + +.backgroundUpload { + height: 100vh; + top: 0; + z-index: 999; + width: 100vw; + position: absolute; + background-color: lightgrey; + opacity: 0.4; +} + +.audio-upload { + top: 100%; + opacity: 0; +} + +.audio-upload.active { + top: 0; + position: absolute; + z-index: 999; + height: 100vh; + width: 100vw; + opacity: 1; +} + +.uploadContainer { + top: 40; + position: absolute; + z-index: 1000; + height: 20vh; + width: 80vw; + opacity: 1; +} + +.loadingImage { + display: inline-flex; + width: max-content; +} + +.loadingSlab { + position: relative; + width: 30px; + height: 30px; + margin: 10; + border-radius: 20px; + opacity: 0.3; + background-color: black; +} \ No newline at end of file diff --git a/src/mobile/AudioUpload.tsx b/src/mobile/AudioUpload.tsx new file mode 100644 index 000000000..7ea11ee84 --- /dev/null +++ b/src/mobile/AudioUpload.tsx @@ -0,0 +1,237 @@ +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 } from 'mobx'; +import { Utils, emptyPath, returnFalse, emptyFunction, returnOne, returnZero, returnTrue } from '../Utils'; +import { Networking } from '../client/Network'; +import { Doc, Opt } from '../fields/Doc'; +import { Cast } from '../fields/Types'; +import { listSpec } from '../fields/Schema'; +import { List } from '../fields/List'; +import { Scripting } from '../client/util/Scripting'; +import MainViewModal from '../client/views/MainViewModal'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { nullAudio } from '../fields/URLField'; +import { Transform } from '../client/util/Transform'; +import { DocumentView } from '../client/views/nodes/DocumentView'; +import { MobileInterface } from './MobileInterface'; + +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(); + +@observer +export class AudioUpload extends React.Component { + @observable error: string = ""; + @observable status: string = ""; + @observable nm: string = "Choose files"; + @observable process: string = ""; + + onClick = async () => { + try { + await Docs.Prototypes.initialize(); + const imgPrev = document.getElementById("img_preview"); + const slab1 = document.getElementById("slab1"); + if (slab1) { + slab1.style.opacity = "1"; + } + if (imgPrev) { + const files: FileList | null = inputRef.current!.files; + const slab2 = document.getElementById("slab2"); + if (slab2) { + slab2.style.opacity = "1"; + } + 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); + const slab3 = document.getElementById("slab3"); + if (slab3) { + slab3.style.opacity = "1"; + } + res.map(async ({ result }) => { + const name = file.name; + if (result instanceof Error) { + return; + } + const path = Utils.prepend(result.accessPaths.agnostic.client); + let doc = null; + console.log("type: " + file.type); + if (file.type === "video/mp4") { + doc = Docs.Create.VideoDocument(path, { _nativeWidth: 200, _width: 200, title: name }); + } else if (file.type === "application/pdf") { + doc = Docs.Create.PdfDocument(path, { _width: 200, title: name }); + } else { + doc = Docs.Create.ImageDocument(path, { _nativeWidth: 200, _width: 200, title: name }); + } + const slab4 = document.getElementById("slab4"); + if (slab4) { + slab4.style.opacity = "1"; + } + const res = await rp.get(Utils.prepend("/getUserDocumentId")); + if (!res) { + throw new Error("No user id returned"); + } + const field = await DocServer.GetRefField(res); + let pending: Opt; + if (field instanceof Doc) { + pending = await Cast(field.mobileUpload, 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"; + const slab5 = document.getElementById("slab5"); + if (slab5) { + slab5.style.opacity = "1"; + } + this.process = "File " + (index + 1).toString() + " Uploaded"; + const slab6 = document.getElementById("slab6"); + if (slab6) { + slab6.style.opacity = "1"; + } + const slab7 = document.getElementById("slab7"); + if (slab7) { + slab7.style.opacity = "1"; + } + + } + }); + } + } else { + this.process = "No file selected"; + } + setTimeout(this.clearUpload, 3000); + } + } catch (error) { + this.error = JSON.stringify(error); + } + } + + // Updates label after a files is selected (so user knows a file is uploaded) + inputLabel = async () => { + 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"; + } + } + + @action + clearUpload = () => { + const slab1 = document.getElementById("slab1"); + if (slab1) { + slab1.style.opacity = "0.4"; + } + const slab2 = document.getElementById("slab2"); + if (slab2) { + slab2.style.opacity = "0.4"; + } + const slab3 = document.getElementById("slab3"); + if (slab3) { + slab3.style.opacity = "0.4"; + } + const slab4 = document.getElementById("slab4"); + if (slab4) { + slab4.style.opacity = "0.4"; + } + const slab5 = document.getElementById("slab5"); + if (slab5) { + slab5.style.opacity = "0.4"; + } + const slab6 = document.getElementById("slab6"); + if (slab6) { + slab6.style.opacity = "0.4"; + } + const slab7 = document.getElementById("slab7"); + if (slab7) { + slab7.style. + opacity = "0.4"; + } + this.nm = "Choose files"; + + if (inputRef.current) { + inputRef.current.value = ""; + } + this.process = ""; + console.log(inputRef.current!.files); + } + + + + private get uploadInterface() { + const audioDoc = Cast(Docs.Create.AudioDocument(nullAudio, { title: "mobile audio" }), Doc) as Doc; + + return ( +
+
+ +
+ 1000} + PanelHeight={() => 1000} + NativeHeight={returnZero} + NativeWidth={returnZero} + renderDepth={0} + focus={emptyFunction} + backgroundColor={() => "white"} + parentActive={returnTrue} + whenActiveChanged={emptyFunction} + bringToFront={emptyFunction} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} + /> +
+ ); + } + + @observable private dialogueBoxOpacity = 1; + @observable private overlayOpacity = 0.4; + + render() { + return ( + + ); + } + +} + + diff --git a/src/mobile/ImageUpload.scss b/src/mobile/ImageUpload.scss index 95c0c2680..b64aac338 100644 --- a/src/mobile/ImageUpload.scss +++ b/src/mobile/ImageUpload.scss @@ -55,6 +55,7 @@ background-color: black; display: inline-block; margin: 10px; + margin-top: 30px; width: 100%; border-radius: 10px; } @@ -106,16 +107,15 @@ .closeUpload { position: absolute; border-radius: 10px; - top: 39.7%; - color: grey; - font-size: 40; - left: 65.8%; + top: 3; + color: black; + font-size: 30; + right: 3; z-index: 1002; padding: 0px 3px; - background: aliceblue; + background: rgba(0, 0, 0, 0); transition: 0.5s ease all; - border: 3px solid; - border-color: black; + border: 0px solid; } .loadingImage { @@ -131,4 +131,5 @@ border-radius: 20px; opacity: 0.3; background-color: black; + transition: all 2s, opacity 1.5s; } \ No newline at end of file diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index b66f0461d..744a45507 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -15,6 +15,8 @@ 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; @@ -29,7 +31,7 @@ export interface ImageUploadProps { const inputRef = React.createRef(); @observer -export class Uploader extends React.Component { +export class Uploader extends React.Component { @observable error: string = ""; @observable status: string = ""; @observable nm: string = "Choose files"; @@ -39,25 +41,22 @@ export class Uploader extends React.Component { try { await Docs.Prototypes.initialize(); const imgPrev = document.getElementById("img_preview"); + // Slab 1 const slab1 = document.getElementById("slab1"); - if (slab1) { - slab1.style.opacity = "1"; - } + if (slab1) slab1.style.opacity = "1"; if (imgPrev) { const files: FileList | null = inputRef.current!.files; + // Slab 2 const slab2 = document.getElementById("slab2"); - if (slab2) { - slab2.style.opacity = "1"; - } + if (slab2) slab2.style.opacity = "1"; 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 const slab3 = document.getElementById("slab3"); - if (slab3) { - slab3.style.opacity = "1"; - } + if (slab3) slab3.style.opacity = "1"; res.map(async ({ result }) => { const name = file.name; if (result instanceof Error) { @@ -67,16 +66,15 @@ export class Uploader extends React.Component { let doc = null; console.log("type: " + file.type); if (file.type === "video/mp4") { - doc = Docs.Create.VideoDocument(path, { _nativeWidth: 200, _width: 200, title: name }); + doc = Docs.Create.VideoDocument(path, { _nativeWidth: 400, _width: 400, title: name }); } else if (file.type === "application/pdf") { - doc = Docs.Create.PdfDocument(path, { _width: 200, title: name }); + doc = Docs.Create.PdfDocument(path, { _nativeWidth: 400, _width: 400, title: name }); } else { - doc = Docs.Create.ImageDocument(path, { _nativeWidth: 200, _width: 200, title: name }); + doc = Docs.Create.ImageDocument(path, { _nativeWidth: 400, _width: 400, title: name }); } + // Slab 4 const slab4 = document.getElementById("slab4"); - if (slab4) { - slab4.style.opacity = "1"; - } + if (slab4) slab4.style.opacity = "1"; const res = await rp.get(Utils.prepend("/getUserDocumentId")); if (!res) { throw new Error("No user id returned"); @@ -84,30 +82,23 @@ export class Uploader extends React.Component { const field = await DocServer.GetRefField(res); let pending: Opt; if (field instanceof Doc) { - pending = await Cast(field.rightSidebarCollection, Doc); + const parent = await Cast(this.props.Document.data, listSpec(Doc)); + const u = CurrentUserUtils.setupMobileUpload(this.props.Document); + if (parent && !parent.includes(u)) parent.push(u); + pending = await Cast(u, Doc); } if (pending) { const data = await Cast(pending.data, listSpec(Doc)); - if (data) { - data.push(doc); - } else { - pending.data = new List([doc]); - } + if (data) data.push(doc); + else pending.data = new List([doc]); this.status = "finished"; const slab5 = document.getElementById("slab5"); - if (slab5) { - slab5.style.opacity = "1"; - } + if (slab5) slab5.style.opacity = "1"; this.process = "File " + (index + 1).toString() + " Uploaded"; const slab6 = document.getElementById("slab6"); - if (slab6) { - slab6.style.opacity = "1"; - } + if (slab6) slab6.style.opacity = "1"; const slab7 = document.getElementById("slab7"); - if (slab7) { - slab7.style.opacity = "1"; - } - + if (slab7) slab7.style.opacity = "1"; } }); } @@ -178,6 +169,9 @@ export class Uploader extends React.Component { private get uploadInterface() { return (
+
+ +
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 4000bee85..612b112e6 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import { library } from '@fortawesome/fontawesome-svg-core'; import { - faTasks, faExternalLinkSquareAlt, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus, + faTasks, 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, @@ -25,6 +25,7 @@ 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"; @@ -39,8 +40,9 @@ import { RadialMenu } from "../client/views/nodes/RadialMenu"; import { UndoManager } from "../client/util/UndoManager"; import { MainView } from "../client/views/MainView"; import { List } from "../fields/List"; +import { AudioUpload } from "./AudioUpload"; -library.add(faTasks, faExternalLinkSquareAlt, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus, +library.add(faTasks, 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, @@ -54,17 +56,18 @@ export class MobileInterface extends React.Component { @computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeMobile, Doc)) : CurrentUserUtils.GuestMobile; } @observable private mainDoc: any = CurrentUserUtils.setupActiveMobileMenu(this.userDoc); @observable private renderView?: () => JSX.Element; - @observable private sidebarActive: boolean = false; - @observable private imageUploadActive: boolean = false; - @observable private menuListView: boolean = false; - @observable private _ink: boolean = false; - - public _activeDoc: Doc = this.mainDoc; - public _homeDoc: Doc = this.mainDoc; - private _homeMenu: boolean = true; - private _child: Doc | null = null; - private _parents: Array = []; - private _library: Doc = CurrentUserUtils.setupLibrary(this.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 + + public _activeDoc: Doc = this.mainDoc; // doc updated as the active mobile page is updated (initially home menu) + public _homeDoc: Doc = this.mainDoc; // home menu as a document + private _homeMenu: boolean = true; // to determine whether currently at home menu + private _child: Doc | null = null; // currently selected document + private _parents: Array = []; // array of parent docs (for pathbar) + private _library: Doc = CurrentUserUtils.setupLibrary(this.userDoc); // to access documents in Dash Web constructor(props: Readonly<{}>) { super(props); @@ -119,7 +122,7 @@ export class MobileInterface extends React.Component { } /** - * Back method for navigating + * Back method for navigating through items */ back = () => { const header = document.getElementById("header") as HTMLElement; @@ -182,7 +185,7 @@ export class MobileInterface extends React.Component { if (this.mainContainer) { const backgroundColor = () => "white"; return ( -
+
window.innerWidth; //The windows width returnHeight = () => (window.innerHeight - 300); //Calculating the windows height (-300 to account for topbar) @@ -224,11 +232,7 @@ export class MobileInterface extends React.Component { handleClick = async (doc: Doc) => { const children = DocListCast(doc.data); if (doc.type !== "collection" && this.sidebarActive) { - this._parents.push(this._activeDoc); - this._activeDoc = doc; - this.switchCurrentView((userDoc: Doc) => doc); - this._homeMenu = false; - this.toggleSidebar(); + this.openFromSidebar(doc); } else if (doc.type === "collection" && children.length === 0) console.log("This collection has no children"); else { this._parents.push(this._activeDoc); @@ -239,6 +243,14 @@ export class MobileInterface extends React.Component { } } + openFromSidebar = (doc: Doc) => { + this._parents.push(this._activeDoc); + this._activeDoc = doc; + this.switchCurrentView((userDoc: Doc) => doc); + this._homeMenu = false; + this.toggleSidebar(); + } + /** * Handles creation of array which is then rendered in renderPathbar() */ @@ -350,14 +362,6 @@ export class MobileInterface extends React.Component {
{this.renderPathbar()} -
); } @@ -377,6 +381,7 @@ export class MobileInterface extends React.Component {
{doc.title}
{doc.type}
+ this.openFromSidebar(doc)} icon="external-link-alt" size="lg" />
); } }); @@ -398,9 +403,13 @@ export class MobileInterface extends React.Component { {this._child ? <> {buttons} -
- Return to library -
+
+ +
Return to library
+
: <> {buttons} @@ -455,7 +464,7 @@ export class MobileInterface extends React.Component { return
@@ -492,21 +501,45 @@ export class MobileInterface extends React.Component { } } + undo = () => { + if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc) { + return (<> +
{ + UndoManager.Undo(); + e.stopPropagation(); + }}> + +
+ ); + } + } + + redo = () => { + if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc) { + return (<> +
{ + UndoManager.Redo(); + e.stopPropagation(); + }}> + +
+ ); + } + } + // Button for switching into ink mode drawInk = () => { if (this._activeDoc._viewType === "docking") { return ( <> - {/*
{ - UndoManager.Undo(); - e.stopPropagation(); - }}> - -
*/}
- {/*
{ - UndoManager.Redo(); - e.stopPropagation(); - }}> - ); + } + } + + // Mobile doc button for uploading + upload = () => { + if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc) { + return ( + <> +
+ -
*/} +
); } } // Button to download images on the mobile downloadDocument = () => { - if (this._activeDoc.type === "image") { + if (this._activeDoc.type === "image" || this._activeDoc.type === "pdf" || this._activeDoc.type === "video") { const url = this._activeDoc["data-path"]?.toString(); return
{ - const audioRightSidebar = Cast(Doc.UserDoc().rightSidebarCollection, Doc) as Doc; - const audioDoc = this._activeDoc; - const data = Cast(audioRightSidebar.data, listSpec(Doc)); - - if (data) { - data.push(audioDoc); - } - } + // // 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._activeDoc; + // const data = Cast(audioRightSidebar.data, listSpec(Doc)); - panelHeight = () => window.innerHeight; - panelWidth = () => window.innerWidth; + // if (data) { + // data.push(audioDoc); + // } + // } // Button for pinning images to presentation pinToPresentation = () => { // Only making button available if it is an image - if (this._activeDoc.type === "image") { + if (!(this._activeDoc.type === "collection" || this._activeDoc.type === "presentation")) { const isPinned = this._activeDoc && Doc.isDocPinned(this._activeDoc); return
{ if (this._homeDoc._viewType = "stacking") { @@ -635,7 +671,7 @@ export class MobileInterface extends React.Component { } } - // Logics for switching the menu into the stacking view + // Logic for switching the menu into the stacking view @action changeToListView = () => { if (this._homeDoc._viewType = "masonry") { @@ -674,29 +710,16 @@ export class MobileInterface extends React.Component { @action toggleUpload = () => this.imageUploadActive = !this.imageUploadActive + // For toggling image upload pop up + @action + toggleAudio = () => this.audioUploadActive = !this.audioUploadActive + // For closing the image upload pop up @action closeUpload = () => { this.imageUploadActive = false; } - // Returns the image upload pop up - uploadImage = () => { - if (this.imageUploadActive) { - console.log("active"); - } else if (!this.imageUploadActive) { - - } - return ( -
-
- -
- -
- ); - } - displayRadialMenu = () => { if (this._activeDoc.type === "collection" && this._activeDoc !== this._homeDoc) { return ; @@ -713,7 +736,10 @@ export class MobileInterface extends React.Component {
- {this.uploadImage()} + +
+
+
{this.switchMenuView()} {this.inkMenu()} @@ -721,8 +747,11 @@ export class MobileInterface extends React.Component {
{this.pinToPresentation()} {this.downloadDocument()} - {this.drawInk()} - {this.uploadAudioButton()} + {this.undo()} + {this.redo()} + {this.upload()} + {/* {this.drawInk()} */} + {/* {this.uploadAudioButton()} */}
{this.displayWorkspaces()} {this.renderDefaultContent()} @@ -738,7 +767,7 @@ export class MobileInterface extends React.Component { Scripting.addGlobal(function switchMobileView(doc: (userDoc: Doc) => Doc, renderView?: () => JSX.Element, onSwitch?: () => void) { return MobileInterface.Instance.switchCurrentView(doc, renderView, onSwitch); }); Scripting.addGlobal(function openMobilePresentation() { return MobileInterface.Instance.setupDefaultPresentation(); }); Scripting.addGlobal(function toggleMobileSidebar() { return MobileInterface.Instance.toggleSidebar(); }); -Scripting.addGlobal(function openMobileAudio() { return MobileInterface.Instance.recordAudio(); }); +Scripting.addGlobal(function openMobileAudio() { return MobileInterface.Instance.toggleAudio(); }); Scripting.addGlobal(function openMobileSettings() { return SettingsManager.Instance.open(); }); Scripting.addGlobal(function switchToLibrary() { return MobileInterface.Instance.switchToLibrary(); }); Scripting.addGlobal(function uploadImageMobile() { return MobileInterface.Instance.toggleUpload(); }); diff --git a/src/mobile/MobileMenu.scss b/src/mobile/MobileMenu.scss index 6304ff5e4..87731655a 100644 --- a/src/mobile/MobileMenu.scss +++ b/src/mobile/MobileMenu.scss @@ -175,6 +175,11 @@ body { z-index: 200; } +.open { + right: 20px; + position: absolute; +} + .left { width: 100%; height: 100%; @@ -262,15 +267,17 @@ body { .docButton { position: relative; width: 100px; + display: flex; height: 100px; font-size: 70px; - padding: 5px; text-align: center; - border-style: solid; - border-radius: 50px; - border-width: 5px; + border: 3px solid black; margin: 20px; z-index: 100; + border-radius: 100%; + justify-content: center; + flex-direction: column; + align-items: center; } .docButtonContainer { -- cgit v1.2.3-70-g09d2 From e7372931b9d28c141aaec9552041b5644c2f415a Mon Sep 17 00:00:00 2001 From: geireann <60007097+geireann@users.noreply.github.com> Date: Fri, 26 Jun 2020 03:37:08 +0800 Subject: Merge branch 'master' into mobile_revision_direct And changes to UI of record and image upload --- src/client/util/CurrentUserUtils.ts | 12 +- src/client/util/DragManager.ts | 2 +- src/client/views/DocumentButtonBar.tsx | 63 +----- src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/GlobalKeyHandler.ts | 2 + src/client/views/MainView.tsx | 11 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 4 +- src/client/views/globalCssVariables.scss | 1 + src/client/views/linking/LinkMenu.scss | 4 + src/client/views/linking/LinkMenu.tsx | 37 +-- src/client/views/nodes/AudioBox.scss | 71 +----- src/client/views/nodes/AudioBox.tsx | 2 +- src/client/views/nodes/DocumentLinksButton.scss | 38 ++++ src/client/views/nodes/DocumentLinksButton.tsx | 104 +++++++++ src/client/views/nodes/DocumentView.tsx | 28 ++- src/client/views/nodes/LinkAnchorBox.tsx | 8 + src/client/views/nodes/LinkDocPreview.tsx | 107 +++++++++ .../views/nodes/formattedText/RichTextMenu.tsx | 9 +- src/mobile/AudioUpload.scss | 41 +++- src/mobile/AudioUpload.tsx | 249 +++++++-------------- src/mobile/ImageUpload.scss | 61 ++--- src/mobile/ImageUpload.tsx | 66 +++--- src/mobile/MobileInterface.tsx | 29 ++- src/mobile/MobileMenu.scss | 1 + 24 files changed, 549 insertions(+), 403 deletions(-) create mode 100644 src/client/views/nodes/DocumentLinksButton.scss create mode 100644 src/client/views/nodes/DocumentLinksButton.tsx create mode 100644 src/client/views/nodes/LinkDocPreview.tsx (limited to 'src/mobile/ImageUpload.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index efdc943fa..823a99436 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -474,12 +474,12 @@ export class CurrentUserUtils { 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: "folder-open", click: 'openWorkspaces()', backgroundColor: "#ffd6d6", info: "Access your Workspaces from your mobile, and navigate through all of your documents. " }, - { title: "RECORD", icon: "microphone", click: 'openMobileAudio()', backgroundColor: "#ffbfbf", info: "Use your phone to record and upload audio onto Dash Web." }, - { title: "UPLOAD", icon: "upload", click: 'uploadImageMobile()', backgroundColor: "#ff9e9e", info: "Upload images or videos from your mobile device so they can be accessed on Dash Web." }, - { title: "PRESENTATION", icon: "desktop", click: 'openMobilePresentation()', backgroundColor: "#ff8080", info: "Use your phone as a remote for you presentation." }, - { title: "MOBILE UPLOAD", icon: "mobile", click: 'switchToMobileUploads()', backgroundColor: "#ff7373", info: "Access the collection of your mobile uploads." }, - { title: "SETTINGS", icon: "cog", click: 'openMobileSettings()', backgroundColor: "#ff5e5e", info: "Change your password, log out, or manage your account security." } + { title: "WORKSPACES", icon: "bars", click: 'openMobileWorkspaces()', 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: "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: "SETTINGS", icon: "cog", click: 'openMobileSettings()', backgroundColor: "lightgrey", info: "Change your password, log out, or manage your account security." } ]; return docProtoData.filter(d => !buttons || !buttons.includes(d.title)).map(data => this.mobileButton({ diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 91bc51101..417ddf989 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -353,7 +353,7 @@ export namespace DragManager { const dragElement = ele.parentNode === dragDiv ? ele : ele.cloneNode(true) as HTMLElement; const rect = ele.getBoundingClientRect(); const scaleX = rect.width / ele.offsetWidth, - scaleY = rect.height / ele.offsetHeight; + scaleY = ele.offsetHeight ? rect.height / ele.offsetHeight : scaleX; elesCont.left = Math.min(rect.left, elesCont.left); elesCont.top = Math.min(rect.top, elesCont.top); elesCont.right = Math.max(rect.right, elesCont.right); diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 62a95116f..fcaea0f0b 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -1,28 +1,28 @@ import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; -import { faArrowAltCircleDown, faPhotoVideo, faArrowAltCircleUp, faArrowAltCircleRight, faCheckCircle, faCloudUploadAlt, faLink, faShare, faStopCircle, faSyncAlt, faTag, faTimes } from '@fortawesome/free-solid-svg-icons'; +import { faArrowAltCircleDown, faArrowAltCircleRight, faArrowAltCircleUp, faCheckCircle, faCloudUploadAlt, faLink, faPhotoVideo, faShare, faStopCircle, faSyncAlt, faTag, faTimes } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast } from "../../fields/Doc"; import { RichTextField } from '../../fields/RichTextField'; -import { NumCast, StrCast, Cast } from "../../fields/Types"; +import { Cast, NumCast } from "../../fields/Types"; import { emptyFunction, setupMoveUpEvents } from "../../Utils"; +import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager'; import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils'; +import { Docs, DocUtils } from '../documents/Documents'; +import { DragManager } from '../util/DragManager'; import { UndoManager } from "../util/UndoManager"; import { CollectionDockingView, DockedFrameRenderer } from './collections/CollectionDockingView'; import { ParentDocSelector } from './collections/ParentDocumentSelector'; import './collections/ParentDocumentSelector.scss'; import './DocumentButtonBar.scss'; -import { LinkMenu } from "./linking/LinkMenu"; +import { MetadataEntryMenu } from './MetadataEntryMenu'; import { DocumentView } from './nodes/DocumentView'; import { GoogleRef } from "./nodes/formattedText/FormattedTextBox"; import { TemplateMenu } from "./TemplateMenu"; import { Template, Templates } from "./Templates"; import React = require("react"); -import { DragManager } from '../util/DragManager'; -import { MetadataEntryMenu } from './MetadataEntryMenu'; -import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager'; -import { Docs } from '../documents/Documents'; +import { DocumentLinksButton } from './nodes/DocumentLinksButton'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -113,39 +113,6 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV get view0() { return this.props.views()?.[0]; } - @action - onLinkButtonMoved = (e: PointerEvent) => { - if (this._linkButton.current !== null) { - const linkDrag = UndoManager.StartBatch("Drag Link"); - this.view0 && DragManager.StartLinkDrag(this._linkButton.current, this.view0.props.Document, e.pageX, e.pageY, { - dragComplete: dropEv => { - const linkDoc = dropEv.linkDragData?.linkDocument as Doc; // equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop - if (this.view0 && linkDoc) { - !linkDoc.linkRelationship && (Doc.GetProto(linkDoc).linkRelationship = "hyperlink"); - - // we want to allow specific views to handle the link creation in their own way (e.g., rich text makes text hyperlinks) - // the dragged view can regiser a linkDropCallback to be notified that the link was made and to update their data structures - // however, the dropped document isn't so accessible. What we do is set the newly created link document on the documentView - // The documentView passes a function prop returning this link doc to its descendants who can react to changes to it. - dropEv.linkDragData?.linkDropCallback?.(dropEv.linkDragData); - runInAction(() => this.view0!._link = linkDoc); - setTimeout(action(() => this.view0!._link = undefined), 0); - } - linkDrag?.end(); - }, - hideSource: false - }); - return true; - } - return false; - } - - - onLinkButtonDown = (e: React.PointerEvent): void => { - setupMoveUpEvents(this, e, this.onLinkButtonMoved, emptyFunction, emptyFunction); - } - - @computed get considerGoogleDocsPush() { const targetDoc = this.view0?.props.Document; @@ -235,20 +202,6 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
; } - @computed - get linkButton() { - const view0 = this.view0; - const linkCount = view0 && DocListCast(view0.props.Document.links).length; - return !view0 ? (null) :
- }> -
- {linkCount ? linkCount : } -
-
-
; - } - @computed get metadataButton() { const view0 = this.view0; @@ -318,7 +271,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV const considerPush = isText && this.considerGoogleDocsPush; return
- {this.linkButton} +
{this.templateButton} diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index beb6155ca..d7b0ab7a9 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -552,7 +552,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> onPointerDown={this.onRadiusDown} onContextMenu={(e) => e.preventDefault()}>
-
+
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 27755737e..7bc8cf6a7 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -19,6 +19,7 @@ import { MarqueeView } from "./collections/collectionFreeForm/MarqueeView"; import { DocumentDecorations } from "./DocumentDecorations"; import { MainView } from "./MainView"; import { DocumentView } from "./nodes/DocumentView"; +import { DocumentLinksButton } from "./nodes/DocumentLinksButton"; const modifiers = ["control", "meta", "shift", "alt"]; type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise; @@ -77,6 +78,7 @@ export default class KeyManager { // MarqueeView.DragMarquee = !MarqueeView.DragMarquee; // bcz: this needs a better disclosure UI break; case "escape": + DocumentLinksButton.StartLink = undefined; const main = MainView.Instance; Doc.SetSelectedTool(InkTool.None); if (main.isPointerDown) { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 97953452d..4e2c067ac 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -5,7 +5,7 @@ import { 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, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faQuoteLeft + faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faQuoteLeft, faSortAmountDown } from '@fortawesome/free-solid-svg-icons'; import { ANTIMODEMENU_HEIGHT } from './globalCssVariables.scss'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; @@ -55,6 +55,9 @@ import { TimelineMenu } from './animationtimeline/TimelineMenu'; import { SnappingManager } from '../util/SnappingManager'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { DocumentManager } from '../util/DocumentManager'; +import { DocumentLinksButton } from './nodes/DocumentLinksButton'; +import { LinkMenu } from './linking/LinkMenu'; +import { LinkDocPreview } from './nodes/LinkDocPreview'; @observer export class MainView extends React.Component { @@ -135,7 +138,7 @@ export class MainView extends React.Component { 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, faTrashAlt, faAngleRight, faBell, - faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faQuoteLeft); + faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faQuoteLeft, faSortAmountDown); this.initEventListeners(); this.initAuthenticationRouters(); } @@ -578,6 +581,10 @@ export class MainView extends React.Component { {this.mainContent} + {DocumentLinksButton.EditLink ? : (null)} + {LinkDocPreview.LinkInfo ? : (null)} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index dc62c48b7..42aa0f58e 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -47,6 +47,7 @@ import { Timeline } from "../../animationtimeline/Timeline"; import { SnappingManager } from "../../../util/SnappingManager"; import { ActiveInkColor, ActiveInkWidth, ActiveInkBezierApprox } from "../../InkingStroke"; import { DocumentType } from "../../../documents/DocumentTypes"; +import { DocumentLinksButton } from "../../nodes/DocumentLinksButton"; library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard, faFileUpload); @@ -245,7 +246,7 @@ export class CollectionFreeFormView extends CollectionSubView { if (this.layoutDoc.targetScale && (Math.abs(e.pageX - this._downX) < 3 && Math.abs(e.pageY - this._downY) < 3)) { if (Date.now() - this._lastTap < 300) { + runInAction(() => DocumentLinksButton.StartLink = undefined); const docpt = this.getTransform().transformPoint(e.clientX, e.clientY); this.scaleAtPt(docpt, 1); e.stopPropagation(); diff --git a/src/client/views/globalCssVariables.scss b/src/client/views/globalCssVariables.scss index 4e85fe0ca..3e54d001b 100644 --- a/src/client/views/globalCssVariables.scss +++ b/src/client/views/globalCssVariables.scss @@ -12,6 +12,7 @@ $lighter-alt-accent: rgb(207, 220, 240); $darker-alt-accent: rgb(178, 206, 248); $intermediate-color: #9c9396; $dark-color: #121721; +$link-color: lightBlue; $antimodemenu-height: 35px; // fonts $sans-serif: "Noto Sans", diff --git a/src/client/views/linking/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss index 7dee22f66..c372e7098 100644 --- a/src/client/views/linking/LinkMenu.scss +++ b/src/client/views/linking/LinkMenu.scss @@ -8,6 +8,10 @@ .linkMenu-list { max-height: 200px; overflow-y: scroll; + position: absolute; + z-index: 10; + background: $link-color; + min-width: 150px } .linkMenu-group { diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx index 56f40ad69..0fcc0f0b9 100644 --- a/src/client/views/linking/LinkMenu.tsx +++ b/src/client/views/linking/LinkMenu.tsx @@ -4,11 +4,12 @@ import { DocumentView } from "../nodes/DocumentView"; import { LinkEditor } from "./LinkEditor"; import './LinkMenu.scss'; import React = require("react"); -import { Doc } from "../../../fields/Doc"; +import { Doc, Opt } from "../../../fields/Doc"; import { LinkManager } from "../../util/LinkManager"; import { LinkMenuGroup } from "./LinkMenuGroup"; import { faTrash } from '@fortawesome/free-solid-svg-icons'; import { library } from "@fortawesome/fontawesome-svg-core"; +import { DocumentLinksButton } from "../nodes/DocumentLinksButton"; library.add(faTrash); @@ -16,16 +17,29 @@ interface Props { docView: DocumentView; changeFlyout: () => void; addDocTab: (document: Doc, where: string) => boolean; + location: number[]; } @observer export class LinkMenu extends React.Component { @observable private _editingLink?: Doc; + @observable private _linkMenuRef: Opt; + @action + onClick = (e: PointerEvent) => { + if (!Array.from(this._linkMenuRef?.getElementsByTagName((e.target as HTMLElement).tagName) || []).includes(e.target as any)) { + DocumentLinksButton.EditLink = undefined; + } + } @action componentDidMount() { this._editingLink = undefined; + document.addEventListener("pointerdown", this.onClick); + } + + componentWillUnmount() { + document.removeEventListener("pointerdown", this.onClick); } clearAllLinks = () => { @@ -56,20 +70,11 @@ export class LinkMenu extends React.Component { render() { const sourceDoc = this.props.docView.props.Document; const groups: Map = LinkManager.Instance.getRelatedGroupedLinks(sourceDoc); - if (this._editingLink === undefined) { - return ( -
- {/* */} - {/* */} -
- {this.renderAllGroups(groups)} -
-
- ); - } else { - return ( - this._editingLink = undefined)}> - ); - } + return
this._linkMenuRef = r} style={{ left: this.props.location[0], top: this.props.location[1] }}> + {!this._editingLink ? + this.renderAllGroups(groups) : + this._editingLink = undefined)} /> + } +
; } } \ No newline at end of file diff --git a/src/client/views/nodes/AudioBox.scss b/src/client/views/nodes/AudioBox.scss index 43dd698ad..b5d113ca0 100644 --- a/src/client/views/nodes/AudioBox.scss +++ b/src/client/views/nodes/AudioBox.scss @@ -175,76 +175,29 @@ @media only screen and (max-device-width: 480px) { - - .audiobox-container, - .audiobox-container-interactive { - width: max-content; - /* align-self: center; */ - left: 50%; - top: 40%; - transform: translate(-50%, 0); - height: 100px; - position: absolute; - display: flex; - pointer-events: all; - /* cursor: default; */ - } - - .audiobox-container .audiobox-buttons, - .audiobox-container-interactive .audiobox-buttons { - display: flex; - width: 500px; - /* left: 50%; */ - /* transform: translate(-50%,0); */ - align-items: center; - } - .audiobox-dictation { + font-size: 5em; + display: flex; width: 100; - height: 100; - font-size: 50; - /* background-color: white; */ + justify-content: center; + flex-direction: column; + align-items: center; } - .audiobox-container .audiobox-record-interactive, - .audiobox-container-interactive .audiobox-record-interactive { - width: 95%; - user-select: none; - font-size: 50px; - font-weight: 100; - left: 5%; + .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 { - position: relative; - align-self: center; - width: 50px; - height: max-content; - padding: 0; - } - - .audiobox-container .audiobox-controls .audiobox-player, - .audiobox-container-interactive .audiobox-controls .audiobox-player { - margin-top: auto; - margin-bottom: auto; - width: 100%; - height: 100%; - position: relative; - padding-right: 5px; - display: flex; - } - - .audiobox-container .audiobox-controls, - .audiobox-container-interactive .audiobox-controls { - width: 500px; - height: 100%; - position: relative; - display: flex; - padding-left: 2px; + width: 70px; } } \ No newline at end of file diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index cb0582d87..d5288fff6 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -193,7 +193,7 @@ export class AudioBox extends ViewBoxBaseComponent { + private _linkButton = React.createRef(); + + @action + onLinkButtonMoved = (e: PointerEvent) => { + if (this._linkButton.current !== null) { + const linkDrag = UndoManager.StartBatch("Drag Link"); + this.props.View && DragManager.StartLinkDrag(this._linkButton.current, this.props.View.props.Document, e.pageX, e.pageY, { + dragComplete: dropEv => { + const linkDoc = dropEv.linkDragData?.linkDocument as Doc; // equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop + if (this.props.View && linkDoc) { + !linkDoc.linkRelationship && (Doc.GetProto(linkDoc).linkRelationship = "hyperlink"); + + // we want to allow specific views to handle the link creation in their own way (e.g., rich text makes text hyperlinks) + // the dragged view can regiser a linkDropCallback to be notified that the link was made and to update their data structures + // however, the dropped document isn't so accessible. What we do is set the newly created link document on the documentView + // The documentView passes a function prop returning this link doc to its descendants who can react to changes to it. + dropEv.linkDragData?.linkDropCallback?.(dropEv.linkDragData); + runInAction(() => this.props.View._link = linkDoc); + setTimeout(action(() => this.props.View._link = undefined), 0); + } + linkDrag?.end(); + }, + hideSource: false + }); + return true; + } + return false; + } + + @observable static StartLink: DocumentView | undefined; + onLinkButtonDown = (e: React.PointerEvent): void => { + setupMoveUpEvents(this, e, this.onLinkButtonMoved, emptyFunction, action((e, doubleTap) => { + if (doubleTap) { + DocumentLinksButton.StartLink = this.props.View; + } else { + DocumentLinksButton.EditLink = this.props.View; + DocumentLinksButton.EditLinkLoc = [e.clientX + 10, e.clientY]; + } + })); + } + completeLink = (e: React.PointerEvent): void => { + setupMoveUpEvents(this, e, returnFalse, emptyFunction, action((e, doubleTap) => { + if (doubleTap) { + if (DocumentLinksButton.StartLink === this.props.View) { + DocumentLinksButton.StartLink = undefined; + } else { + DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View && + DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag"); + } + } + })); + } + + @observable + public static EditLink: DocumentView | undefined; + public static EditLinkLoc: number[] = [0, 0]; + + @computed + get linkButton() { + const links = DocListCast(this.props.View.props.Document.links); + return (!links.length || links[0].hidden) && !this.props.AlwaysOn ? (null) : +
+
LinkDocPreview.LinkInfo = undefined)} + onPointerEnter={action(e => LinkDocPreview.LinkInfo = { + addDocTab: this.props.View.props.addDocTab, + linkSrc: this.props.View.props.Document, + linkDoc: links[0], + Location: [e.clientX, e.clientY + 20] + })} > + {links.length ? links.length : } +
+ {DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View ?
: (null)} + {DocumentLinksButton.StartLink === this.props.View ?
: (null)} +
; + } + render() { + return this.linkButton; + } +} \ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index d31ec8c1a..afd28534e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -42,6 +42,7 @@ import { LinkAnchorBox } from './LinkAnchorBox'; import { RadialMenu } from './RadialMenu'; import React = require("react"); import { MobileInterface } from '../../../mobile/MobileInterface'; +import { DocumentLinksButton } from './DocumentLinksButton'; library.add(fa.faEdit, fa.faTrash, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faCompressArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faAlignCenter, fa.faCaretSquareRight, fa.faSquare, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faLink, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock, fa.faLock, fa.faLaptopCode, fa.faMale, @@ -585,10 +586,14 @@ export class DocumentView extends DocComponent(Docu toggleLinkButtonBehavior = (): void => { if (this.Document.isLinkButton || this.layoutDoc.onClick || this.Document.ignoreClick) { this.Document.isLinkButton = false; + const first = DocListCast(this.Document.links).find(d => d instanceof Doc); + first && (first.hidden = false); this.Document.ignoreClick = false; this.layoutDoc.onClick = undefined; } else { this.Document.isLinkButton = true; + const first = DocListCast(this.Document.links).find(d => d instanceof Doc); + first && (first.hidden = true); this.Document.followLinkZoom = false; this.Document.followLinkLocation = undefined; } @@ -598,8 +603,12 @@ export class DocumentView extends DocComponent(Docu toggleFollowInPlace = (): void => { if (this.Document.isLinkButton) { this.Document.isLinkButton = false; + const first = DocListCast(this.Document.links).find(d => d instanceof Doc); + first && (first.hidden = false); } else { this.Document.isLinkButton = true; + const first = DocListCast(this.Document.links).find(d => d instanceof Doc); + first && (first.hidden = true); this.Document.followLinkZoom = true; this.Document.followLinkLocation = "inPlace"; } @@ -609,6 +618,8 @@ export class DocumentView extends DocComponent(Docu toggleFollowOnRight = (): void => { if (this.Document.isLinkButton) { this.Document.isLinkButton = false; + const first = DocListCast(this.Document.links).find(d => d instanceof Doc); + first && (first.hidden = false); } else { this.Document.isLinkButton = true; this.Document.followLinkZoom = false; @@ -737,10 +748,8 @@ export class DocumentView extends DocComponent(Docu const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : []; const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null); templateDoc && optionItems.push({ description: "Open Template ", event: () => this.props.addDocTab(templateDoc, "onRight"), icon: "eye" }); - if (!options) { - options = { description: "Options...", subitems: optionItems, icon: "compass" }; - cm?.addItem(options); - } + optionItems.push({ description: "Toggle Show Each Link Dot", event: () => this.layoutDoc.showLinks = !this.layoutDoc.showLinks, icon: "eye" }); + !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "compass" }); const existingOnClick = cm?.findByDescription("OnClick..."); const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : []; @@ -1039,7 +1048,8 @@ export class DocumentView extends DocComponent(Docu select={this.select} onClick={this.onClickHandler} layoutKey={this.finalLayoutKey} /> - {this.anchors} + {this.layoutDoc.showLinks ? this.anchors : (null)} + {this.props.forcedBackgroundColor?.(this.Document) === "transparent" || this.props.dontRegisterView ? (null) : }
); } @@ -1063,7 +1073,7 @@ export class DocumentView extends DocComponent(Docu anchorPanelHeight = () => this.props.PanelHeight() || 1; @computed get anchors() { TraceMobx(); - return this.layoutDoc.presBox ? (null) : DocListCast(this.Document.links).filter(d => !d.hidden && this.isNonTemporalLink).map((d, i) => + return this.props.forcedBackgroundColor?.(this.Document) === "transparent" || this.layoutDoc.presBox || this.props.dontRegisterView ? (null) : DocListCast(this.Document.links).filter(d => !d.hidden && this.isNonTemporalLink).map((d, i) => (Docu PanelWidth={this.anchorPanelWidth} PanelHeight={this.anchorPanelHeight} ContentScaling={returnOne} + dontRegisterView={false} forcedBackgroundColor={returnTransparent} removeDocument={this.hideLinkAnchor} pointerEvents={false} @@ -1194,7 +1205,10 @@ export class DocumentView extends DocComponent(Docu color: StrCast(this.layoutDoc.color, "inherit"), outline: highlighting && !borderRounding ? `${highlightColors[fullDegree]} ${highlightStyles[fullDegree]} ${localScale}px` : "solid 0px", border: highlighting && borderRounding ? `${highlightStyles[fullDegree]} ${highlightColors[fullDegree]} ${localScale}px` : undefined, - boxShadow: this.props.Document.isTemplateForField ? "black 0.2vw 0.2vw 0.8vw" : undefined, + boxShadow: this.Document.isLinkButton && !this.props.dontRegisterView && this.props.forcedBackgroundColor?.(this.Document) !== "transparent" ? + StrCast(this.props.Document._linkButtonShadow, "lightblue 0em 0em 1em") : + this.props.Document.isTemplateForField ? "black 0.2vw 0.2vw 0.8vw" : + undefined, background: finalColor, opacity: finalOpacity, fontFamily: StrCast(this.Document._fontFamily, "inherit"), diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index 2b64cdab6..2bcc6168b 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -18,6 +18,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { SelectionManager } from "../../util/SelectionManager"; import { TraceMobx } from "../../../fields/util"; import { Id } from "../../../fields/FieldSymbols"; +import { LinkDocPreview } from "./LinkDocPreview"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -132,6 +133,13 @@ export class LinkAnchorBox extends ViewBoxBaseComponent LinkDocPreview.LinkInfo = undefined)} + onPointerEnter={action(e => LinkDocPreview.LinkInfo = { + addDocTab: this.props.addDocTab, + linkSrc: this.props.ContainingCollectionDoc!, + linkDoc: this.rootDoc, + Location: [e.clientX, e.clientY + 20] + })} onPointerDown={this.onPointerDown} onClick={this.onClick} title={targetTitle} onContextMenu={this.specificContextMenu} ref={this._ref} style={{ background: c, diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx new file mode 100644 index 000000000..126dc240a --- /dev/null +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -0,0 +1,107 @@ +import { action, computed, observable, runInAction } from 'mobx'; +import { observer } from "mobx-react"; +import wiki from "wikijs"; +import { Doc, DocCastAsync, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; +import { Cast, FieldValue, NumCast } from "../../../fields/Types"; +import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero } from "../../../Utils"; +import { Docs } from "../../documents/Documents"; +import { DocumentManager } from "../../util/DocumentManager"; +import { Transform } from "../../util/Transform"; +import { ContentFittingDocumentView } from "./ContentFittingDocumentView"; +import React = require("react"); +import { DocumentView } from './DocumentView'; + +interface Props { + linkDoc?: Doc; + linkSrc?: Doc; + href?: string; + backgroundColor: (doc: Doc) => string; + addDocTab: (document: Doc, where: string) => boolean; + location: number[]; +} +@observer +export class LinkDocPreview extends React.Component { + @observable public static LinkInfo: Opt<{ linkDoc?: Doc; addDocTab: (document: Doc, where: string) => boolean, linkSrc: Doc; href?: string; Location: number[] }>; + @observable _targetDoc: Opt; + @observable _toolTipText = ""; + + componentDidUpdate() { this.updatePreview() } + componentDidMount() { this.updatePreview() } + async updatePreview() { + const linkDoc = this.props.linkDoc; + const linkSrc = this.props.linkSrc; + if (this.props.href) { + if (this.props.href.startsWith("https://en.wikipedia.org/wiki/")) { + wiki().page(this.props.href.replace("https://en.wikipedia.org/wiki/", "")).then(page => page.summary().then(action(summary => this._toolTipText = summary.substring(0, 500)))); + } else { + runInAction(() => this._toolTipText = "external => " + this.props.href); + } + } else if (linkDoc && linkSrc) { + const anchor = FieldValue(Doc.AreProtosEqual(FieldValue(Cast(linkDoc.anchor1, Doc)), linkSrc) ? Cast(linkDoc.anchor2, Doc) : (Cast(linkDoc.anchor1, Doc)) || linkDoc); + const target = anchor?.annotationOn ? await DocCastAsync(anchor.annotationOn) : anchor; + runInAction(() => { + this._toolTipText = ""; + this._targetDoc = target; + if (anchor !== this._targetDoc && anchor && this._targetDoc) { + this._targetDoc._scrollY = NumCast(anchor?.y); + } + }); + } + } + pointerDown = (e: React.PointerEvent) => { + if (this.props.linkDoc && this.props.linkSrc) { + DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.linkSrc, + (doc: Doc, followLinkLocation: string) => this.props.addDocTab(doc, e.ctrlKey ? "inTab" : followLinkLocation)); + } else if (this.props.href) { + this.props.addDocTab(Docs.Create.WebDocument(this.props.href, { title: this.props.href, _width: 200, _height: 400, UseCors: true }), "onRight"); + } + } + width = () => Math.min(350, NumCast(this._targetDoc?.[WidthSym](), 350)); + height = () => Math.min(350, NumCast(this._targetDoc?.[HeightSym](), 350)); + @computed get targetDocView() { + return !this._targetDoc ? +
+
+ {this._toolTipText} +
+
: + ; + } + + render() { + return
+ {this.targetDocView} +
; + } +} \ No newline at end of file diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 5e32b3ef8..839943aac 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -11,7 +11,7 @@ import { EditorState, NodeSelection, TextSelection } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; import { Doc } from "../../../../fields/Doc"; import { DarkPastelSchemaPalette, PastelSchemaPalette } from '../../../../fields/SchemaHeaderField'; -import { Cast, StrCast } from "../../../../fields/Types"; +import { Cast, StrCast, BoolCast } from "../../../../fields/Types"; import { unimplementedFunction, Utils } from "../../../../Utils"; import { DocServer } from "../../../DocServer"; import { LinkManager } from "../../../util/LinkManager"; @@ -72,7 +72,7 @@ export default class RichTextMenu extends AntimodeMenu { super(props); RichTextMenu.Instance = this; this._canFade = false; - this.Pinned = true; + this.Pinned = BoolCast(Doc.UserDoc()["menuRichText-pinned"]); this.fontSizeOptions = [ { mark: schema.marks.pFontSize.create({ fontSize: 7 }), title: "Set font size", label: "7pt", command: this.changeFontSize }, @@ -147,7 +147,6 @@ export default class RichTextMenu extends AntimodeMenu { this.updateFromDash(view, lastState, this.editorProps); } - public MakeLinkToSelection = (linkDocId: string, title: string, location: string, targetDocId: string): string => { if (this.view) { const link = this.view.state.schema.marks.link.create({ href: Utils.prepend("/doc/" + linkDocId), title: title, location: location, linkId: linkDocId, targetId: targetDocId }); @@ -750,7 +749,7 @@ export default class RichTextMenu extends AntimodeMenu { @action toggleMenuPin = (e: React.MouseEvent) => { - this.Pinned = !this.Pinned; + Doc.UserDoc()["menuRichText-pinned"] = this.Pinned = !this.Pinned; if (!this.Pinned) { this.fadeOut(true); } @@ -779,7 +778,7 @@ export default class RichTextMenu extends AntimodeMenu { this.createHighlighterButton(), this.createLinkButton(), this.createBrushButton(), - this.createButton("indent", "Summarize", undefined, this.insertSummarizer), + this.createButton("sort-amount-down", "Summarize", undefined, this.insertSummarizer), this.createButton("quote-left", "Blockquote", undefined, this.insertBlockquote), ]}
; diff --git a/src/mobile/AudioUpload.scss b/src/mobile/AudioUpload.scss index 9fe442e55..6e64d9e2e 100644 --- a/src/mobile/AudioUpload.scss +++ b/src/mobile/AudioUpload.scss @@ -5,8 +5,45 @@ justify-content: center; flex-direction: column; align-items: center; - max-width: 400px; - min-width: 400px; + margin-top: 10px; + height: 400px; + width: 600px; +} + +.upload_label { + position: relative; + font-weight: 700; + color: black; + background-color: rgba(0, 0, 0, 0); + border: solid 3px black; + margin: 10px; + font-size: 30; + height: 70px; + width: 60%; + display: inline-flex; + font-family: sans-serif; + text-transform: uppercase; + justify-content: center; + flex-direction: column; + border-radius: 10px; +} + +.restart_label { + position: relative; + font-weight: 700; + color: black; + background-color: rgba(0, 0, 0, 0); + border: solid 3px black; + margin: 10px; + font-size: 30; + height: 70px; + width: 60%; + display: inline-flex; + font-family: sans-serif; + text-transform: uppercase; + justify-content: center; + flex-direction: column; + border-radius: 10px; } .audio-upload { diff --git a/src/mobile/AudioUpload.tsx b/src/mobile/AudioUpload.tsx index 7ea11ee84..f859b0ba3 100644 --- a/src/mobile/AudioUpload.tsx +++ b/src/mobile/AudioUpload.tsx @@ -5,11 +5,11 @@ import "./ImageUpload.scss"; import React = require('react'); import { DocServer } from '../client/DocServer'; import { observer } from 'mobx-react'; -import { observable, action } from 'mobx'; -import { Utils, emptyPath, returnFalse, emptyFunction, returnOne, returnZero, returnTrue } from '../Utils'; +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 } from '../fields/Types'; +import { Cast, FieldValue } from '../fields/Types'; import { listSpec } from '../fields/Schema'; import { List } from '../fields/List'; import { Scripting } from '../client/util/Scripting'; @@ -38,185 +38,100 @@ export class AudioUpload extends React.Component { @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; - onClick = async () => { - try { - await Docs.Prototypes.initialize(); - const imgPrev = document.getElementById("img_preview"); - const slab1 = document.getElementById("slab1"); - if (slab1) { - slab1.style.opacity = "1"; - } - if (imgPrev) { - const files: FileList | null = inputRef.current!.files; - const slab2 = document.getElementById("slab2"); - if (slab2) { - slab2.style.opacity = "1"; - } - 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); - const slab3 = document.getElementById("slab3"); - if (slab3) { - slab3.style.opacity = "1"; - } - res.map(async ({ result }) => { - const name = file.name; - if (result instanceof Error) { - return; - } - const path = Utils.prepend(result.accessPaths.agnostic.client); - let doc = null; - console.log("type: " + file.type); - if (file.type === "video/mp4") { - doc = Docs.Create.VideoDocument(path, { _nativeWidth: 200, _width: 200, title: name }); - } else if (file.type === "application/pdf") { - doc = Docs.Create.PdfDocument(path, { _width: 200, title: name }); - } else { - doc = Docs.Create.ImageDocument(path, { _nativeWidth: 200, _width: 200, title: name }); - } - const slab4 = document.getElementById("slab4"); - if (slab4) { - slab4.style.opacity = "1"; - } - const res = await rp.get(Utils.prepend("/getUserDocumentId")); - if (!res) { - throw new Error("No user id returned"); - } - const field = await DocServer.GetRefField(res); - let pending: Opt; - if (field instanceof Doc) { - pending = await Cast(field.mobileUpload, 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"; - const slab5 = document.getElementById("slab5"); - if (slab5) { - slab5.style.opacity = "1"; - } - this.process = "File " + (index + 1).toString() + " Uploaded"; - const slab6 = document.getElementById("slab6"); - if (slab6) { - slab6.style.opacity = "1"; - } - const slab7 = document.getElementById("slab7"); - if (slab7) { - slab7.style.opacity = "1"; - } - - } - }); - } - } else { - this.process = "No file selected"; - } - setTimeout(this.clearUpload, 3000); - } - } catch (error) { - this.error = JSON.stringify(error); - } - } - - // Updates label after a files is selected (so user knows a file is uploaded) - inputLabel = async () => { - 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"; - } - } @action clearUpload = () => { - const slab1 = document.getElementById("slab1"); - if (slab1) { - slab1.style.opacity = "0.4"; - } - const slab2 = document.getElementById("slab2"); - if (slab2) { - slab2.style.opacity = "0.4"; - } - const slab3 = document.getElementById("slab3"); - if (slab3) { - slab3.style.opacity = "0.4"; + for (let i = 1; i < 8; i++) { + this.setOpacity(i, "0.2"); } - const slab4 = document.getElementById("slab4"); - if (slab4) { - slab4.style.opacity = "0.4"; - } - const slab5 = document.getElementById("slab5"); - if (slab5) { - slab5.style.opacity = "0.4"; - } - const slab6 = document.getElementById("slab6"); - if (slab6) { - slab6.style.opacity = "0.4"; - } - const slab7 = document.getElementById("slab7"); - if (slab7) { - slab7.style. - opacity = "0.4"; - } - this.nm = "Choose files"; - - if (inputRef.current) { - inputRef.current.value = ""; - } - this.process = ""; - console.log(inputRef.current!.files); + 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; } - + closeUpload = () => { + this.clearUpload(); + MobileInterface.Instance.toggleAudio(); + } private get uploadInterface() { - const audioDoc = Cast(Docs.Create.AudioDocument(nullAudio, { title: "mobile audio" }), Doc) as Doc; - return ( -
-
+ <> +
this.closeUpload()}>
- 1000} - PanelHeight={() => 1000} - NativeHeight={returnZero} - NativeWidth={returnZero} - renderDepth={0} - focus={emptyFunction} - backgroundColor={() => "white"} - parentActive={returnTrue} - whenActiveChanged={emptyFunction} - bringToFront={emptyFunction} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} - /> -
+ +
+ 600} + PanelHeight={() => 400} + NativeHeight={returnZero} + NativeWidth={returnZero} + renderDepth={0} + focus={emptyFunction} + backgroundColor={() => "rgba(0,0,0,0)"} + parentActive={returnTrue} + whenActiveChanged={emptyFunction} + bringToFront={emptyFunction} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} + /> +
+
+ Restart +
+
+ Upload +
+
+
+
+
+
+
+
+
+
+ ); } + setOpacity = (i: number, o: string) => { + const slab = document.getElementById("slab0" + i); + if (slab) { + console.log(slab?.id); + slab.style.opacity = o; + } + } + + // 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.scss b/src/mobile/ImageUpload.scss index b64aac338..890258918 100644 --- a/src/mobile/ImageUpload.scss +++ b/src/mobile/ImageUpload.scss @@ -9,13 +9,19 @@ min-width: 400px; .upload_label { - font-size: 3em; font-weight: 700; - color: white; - background-color: black; - display: inline-block; - margin: 10; - width: 100%; + color: black; + background-color: rgba(0, 0, 0, 0); + border: solid 3px black; + margin: 10px; + font-size: 30; + height: 70px; + width: 80%; + display: flex; + font-family: sans-serif; + text-transform: uppercase; + justify-content: center; + flex-direction: column; border-radius: 10px; } @@ -26,10 +32,6 @@ direction: ltr; } - .upload_label:hover { - background-color: darkred; - } - .button_file { text-align: center; height: 50%; @@ -49,20 +51,31 @@ } .inputfile+label { - font-size: 3em; font-weight: 700; - color: white; - background-color: black; - display: inline-block; + color: black; + background-color: rgba(0, 0, 0, 0); + border: solid 3px black; margin: 10px; + font-size: 30; + height: 70px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; margin-top: 30px; - width: 100%; + width: 80%; + display: flex; + font-family: sans-serif; + text-transform: uppercase; + justify-content: center; + flex-direction: column; border-radius: 10px; } - .inputfile:focus+label, - .inputfile+label:hover { - background-color: darkred; + .inputfile.active+label { + font-style: italic; + color: black; + background-color: lightgreen; + border: solid 3px darkgreen; } .status { @@ -71,16 +84,6 @@ } -.backgroundUpload { - height: 100vh; - top: 0; - z-index: 999; - width: 100vw; - position: absolute; - background-color: lightgrey; - opacity: 0.4; -} - .image-upload { top: 100%; opacity: 0; @@ -129,7 +132,7 @@ height: 30px; margin: 10; border-radius: 20px; - opacity: 0.3; + opacity: 0.2; background-color: black; transition: all 2s, opacity 1.5s; } \ No newline at end of file diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index b712d52cc..6a5a2dd5b 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -43,21 +43,18 @@ export class Uploader extends React.Component { await Docs.Prototypes.initialize(); const imgPrev = document.getElementById("img_preview"); // Slab 1 - const slab1 = document.getElementById("slab1"); - if (slab1) slab1.style.opacity = "1"; + this.setOpacity(1, "1"); if (imgPrev) { const files: FileList | null = inputRef.current!.files; // Slab 2 - const slab2 = document.getElementById("slab2"); - if (slab2) slab2.style.opacity = "1"; + this.setOpacity(2, "1"); 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 - const slab3 = document.getElementById("slab3"); - if (slab3) slab3.style.opacity = "1"; + this.setOpacity(3, "1"); res.map(async ({ result }) => { const name = file.name; if (result instanceof Error) { @@ -74,8 +71,7 @@ export class Uploader extends React.Component { doc = Docs.Create.ImageDocument(path, { _nativeWidth: 400, _width: 400, title: name }); } // Slab 4 - const slab4 = document.getElementById("slab4"); - if (slab4) slab4.style.opacity = "1"; + this.setOpacity(4, "1"); const res = await rp.get(Utils.prepend("/getUserDocumentId")); if (!res) { throw new Error("No user id returned"); @@ -94,13 +90,15 @@ export class Uploader extends React.Component { if (data) data.push(doc); else pending.data = new List([doc]); this.status = "finished"; - const slab5 = document.getElementById("slab5"); - if (slab5) slab5.style.opacity = "1"; + this.setOpacity(5, "1"); // Slab 5 this.process = "File " + (index + 1).toString() + " Uploaded"; - const slab6 = document.getElementById("slab6"); - if (slab6) slab6.style.opacity = "1"; - const slab7 = document.getElementById("slab7"); - if (slab7) slab7.style.opacity = "1"; + 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"; } }); } @@ -129,20 +127,9 @@ export class Uploader extends React.Component { @action clearUpload = () => { - const slab1 = document.getElementById("slab1"); - if (slab1) slab1.style.opacity = "0.4"; - const slab2 = document.getElementById("slab2"); - if (slab2) slab2.style.opacity = "0.4"; - const slab3 = document.getElementById("slab3"); - if (slab3) slab3.style.opacity = "0.4"; - const slab4 = document.getElementById("slab4"); - if (slab4) slab4.style.opacity = "0.4"; - const slab5 = document.getElementById("slab5"); - if (slab5) slab5.style.opacity = "0.4"; - const slab6 = document.getElementById("slab6"); - if (slab6) slab6.style.opacity = "0.4"; - const slab7 = document.getElementById("slab7"); - if (slab7) slab7.style.opacity = "0.4"; + for (let i = 1; i < 8; i++) { + this.setOpacity(i, "0.2"); + } this.nm = "Choose files"; if (inputRef.current) { @@ -152,24 +139,33 @@ export class Uploader extends React.Component { console.log(inputRef.current!.files); } + 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; + } + } private get uploadInterface() { return (
-
+
this.closeUpload()}>
- + +
- -     Upload + Upload
- {/*
Upload
*/} - {/*

{this.status}

-

{this.error}

*/}
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index a1719c015..5894326ab 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import { library } from '@fortawesome/fontawesome-svg-core'; import { - faTasks, faFolderOpen, faAngleDoubleLeft, faExternalLinkSquareAlt, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus, + 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, @@ -43,8 +43,9 @@ 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"; -library.add(faTasks, faFolderOpen, faAngleDoubleLeft, faExternalLinkSquareAlt, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus, +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, @@ -387,13 +388,13 @@ export class MobileInterface extends React.Component { return (
this.handleClick(doc)}> -
{doc.title}
-
{doc.type}
- + key={index}> +
this.handleClick(doc)}> {doc.title}
+
this.handleClick(doc)}>{doc.type}
+ this.handleClick(doc)} className="right" icon="angle-right" size="lg" style={{ display: `${doc.type === "collection" ? "block" : "none"}` }} /> this.openFromSidebar(doc)} icon="external-link-alt" size="lg" /> -
); +
+ ); } }); @@ -440,7 +441,7 @@ export class MobileInterface extends React.Component { } /** - * Handles the Create New Workspace button in the menu + * Handles the Create New Workspace button in the menu (taken from MainView.tsx) */ @action createNewWorkspace = async (id?: string) => { @@ -759,12 +760,7 @@ export class MobileInterface extends React.Component { toggle = this.toggleUpload; } return ( -
-
- -
- -
+ ); } @@ -815,6 +811,7 @@ export class MobileInterface extends React.Component { {this.switchMenuView()} {this.inkMenu()} +
{this.pinToPresentation()} {this.downloadDocument()} @@ -843,6 +840,6 @@ Scripting.addGlobal(function openMobilePresentation() { return MobileInterface.I 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 openWorkspaces() { return MobileInterface.Instance.openWorkspaces(); }); +Scripting.addGlobal(function openMobileWorkspaces() { return MobileInterface.Instance.openWorkspaces(); }); Scripting.addGlobal(function uploadImageMobile() { return MobileInterface.Instance.toggleUpload(); }); Scripting.addGlobal(function switchToMobileUploads() { return MobileInterface.Instance.switchToMobileUploads(); }); diff --git a/src/mobile/MobileMenu.scss b/src/mobile/MobileMenu.scss index 53bc48034..c499e6d1e 100644 --- a/src/mobile/MobileMenu.scss +++ b/src/mobile/MobileMenu.scss @@ -176,6 +176,7 @@ body { .open { right: 20px; + font-size: 35; position: absolute; } -- cgit v1.2.3-70-g09d2 From 991376428130bd80e1e80b5cca52477e45caf679 Mon Sep 17 00:00:00 2001 From: geireann <60007097+geireann@users.noreply.github.com> Date: Tue, 30 Jun 2020 02:34:08 +0800 Subject: css comment fixes + commenting --- src/client/util/CurrentUserUtils.ts | 54 ++- src/client/util/SettingsManager.scss | 10 - src/client/views/AntimodeMenu.scss | 16 - src/client/views/nodes/AudioBox.scss | 8 +- src/client/views/nodes/PDFBox.scss | 188 +++----- src/client/views/nodes/PresBox.scss | 47 +- .../views/presentationview/PresElementBox.scss | 78 +--- src/mobile/AudioUpload.tsx | 84 ++-- src/mobile/ImageUpload.tsx | 61 +-- src/mobile/MobileHome.scss | 101 ----- src/mobile/MobileInterface.scss | 448 ++++++++++++++++++- src/mobile/MobileInterface.tsx | 116 +++-- src/mobile/MobileMenu.scss | 475 --------------------- 13 files changed, 665 insertions(+), 1021 deletions(-) delete mode 100644 src/mobile/MobileHome.scss (limited to 'src/mobile/ImageUpload.tsx') 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(["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(["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(["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(); - @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(); @observer export class Uploader extends React.Component { @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 { } 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 { const field = await DocServer.GetRefField(res); let pending: Opt; 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 { 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 { 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 (
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 {
); } - + // 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(["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
; @@ -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 (<>
{ - 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 (<>
@@ -593,7 +583,6 @@ export class MobileInterface extends React.Component { style={{ backgroundColor: "white", color: "black" }} onClick={e => { window.open(url); - console.log(url); }}> @@ -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 ; @@ -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
{ 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 -- cgit v1.2.3-70-g09d2