diff options
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 10 | ||||
-rw-r--r-- | src/client/views/.DS_Store | bin | 10244 -> 10244 bytes | |||
-rw-r--r-- | src/client/views/MainView.tsx | 64 | ||||
-rw-r--r-- | src/client/views/collections/CollectionDockingView.tsx | 1 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 289 | ||||
-rw-r--r-- | src/client/views/nodes/PresBox.scss | 96 | ||||
-rw-r--r-- | src/client/views/nodes/PresBox.tsx | 107 | ||||
-rw-r--r-- | src/client/views/presentationview/PresElementBox.tsx | 12 |
8 files changed, 366 insertions, 213 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 49377a728..8f65f3e9f 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -836,13 +836,20 @@ export class CurrentUserUtils { } } - // Right sidebar is where mobile uploads are contained + // Sharing sidebar is where shared documents are contained static setupSharingSidebar(doc: Doc) { if (doc["sidebar-sharing"] === undefined) { doc["sidebar-sharing"] = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "Shared Documents", childDropAction: "alias" })); } } + // Import sidebar is where shared documents are contained + static setupImportSidebar(doc: Doc) { + if (doc["sidebar-import"] === undefined) { + doc["sidebar-import"] = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "Imported Documents", childDropAction: "alias" })); + } + } + static setupClickEditorTemplates(doc: Doc) { if (doc["clickFuncs-child"] === undefined) { @@ -913,6 +920,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.setupSharingSidebar(doc); // sets up the right sidebar collection for mobile upload documents and sharing + this.setupImportSidebar(doc); this.setupActiveMobileMenu(doc); // sets up the current mobile menu for Dash Mobile this.setupMenuPanel(doc); this.setupSearchPanel(doc); diff --git a/src/client/views/.DS_Store b/src/client/views/.DS_Store Binary files differindex 489c1666e..c6f3afa14 100644 --- a/src/client/views/.DS_Store +++ b/src/client/views/.DS_Store diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index f5dccd567..80957aebb 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -63,6 +63,9 @@ import { undoBatch } from '../util/UndoManager'; import { WebBox } from './nodes/WebBox'; import * as ReactDOM from 'react-dom'; import { SearchBox } from './search/SearchBox'; +import { SearchUtil } from '../util/SearchUtil'; +import { Networking } from '../Network'; +import * as rp from 'request-promise'; @observer export class MainView extends React.Component { @@ -545,6 +548,7 @@ export class MainView extends React.Component { case "Catalog": panelDoc = Doc.UserDoc()["sidebar-catalog"] as Doc ?? undefined; break; case "Archive": panelDoc = Doc.UserDoc()["sidebar-recentlyClosed"] as Doc ?? undefined; break; case "Settings": SettingsManager.Instance.open(); break; + case "Import": panelDoc = Doc.UserDoc()["sidebar-import"] as Doc ?? undefined; this.importDocument(); break; case "Sharing": panelDoc = Doc.UserDoc()["sidebar-sharing"] as Doc ?? undefined; break; case "UserDoc": panelDoc = Doc.UserDoc()["sidebar-userDoc"] as Doc ?? undefined; break; } @@ -559,6 +563,66 @@ export class MainView extends React.Component { return true; } + + importDocument = async () => { + const inputRef = React.createRef<HTMLInputElement>(); + const sidebar = Cast(Doc.UserDoc()["sidebar-import"], Doc) as Doc; + let process = ''; + let error = ''; + try { + const col = sidebar; + await Docs.Prototypes.initialize(); + const imgPrev = document.getElementById("img_preview"); + if (imgPrev) { + const files: FileList | null = inputRef.current!.files; + if (files && files.length !== 0) { + for (let index = 0; index < files.length; ++index) { + const file = files[index]; + const res = await Networking.UploadFilesToServer(file); + // For each item that the user has selected + res.map(async ({ result }) => { + const name = file.name; + if (result instanceof Error) { + return; + } + const path = Utils.prepend(result.accessPaths.agnostic.client); + let doc = null; + // 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, _fitWidth: true, title: name }); + // Case 3: File is another document type (most likely Image) + } else { + doc = Docs.Create.ImageDocument(path, { _nativeWidth: 400, _width: 400, title: name }); + } + 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<Doc>; + if (field instanceof Doc) { + pending = col; + } + if (pending) { + const data = await Cast(pending.data, listSpec(Doc)); + if (data) data.push(doc); + else pending.data = new List([doc]); + } + }); + } + // Case in which the user pressed upload and no files were selected + } else { + process = "No file selected"; + } + } + } catch (error) { + error = JSON.stringify(error); + } + } + @action closeProperties = () => { CurrentUserUtils.propertiesWidth = 0; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 7e096fa37..9e78ad871 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -723,6 +723,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> { pinDoc.presZoomButton = true; pinDoc.context = curPres; Doc.AddDocToList(curPres, "data", pinDoc); + if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true; if (!DocumentManager.Instance.getDocumentView(curPres)) { CollectionDockingView.AddRightSplit(curPres); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 98ea8998d..3448d2683 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -15,7 +15,7 @@ import { ScriptField } from "../../../../fields/ScriptField"; import { BoolCast, Cast, FieldValue, NumCast, ScriptCast, StrCast } from "../../../../fields/Types"; import { TraceMobx } from "../../../../fields/util"; import { GestureUtils } from "../../../../pen-gestures/GestureUtils"; -import { aggregateBounds, intersectRect, returnFalse, returnOne, returnZero, Utils } from "../../../../Utils"; +import { aggregateBounds, intersectRect, returnFalse, returnOne, returnZero, Utils, setupMoveUpEvents } from "../../../../Utils"; import { CognitiveServices } from "../../../cognitive_services/CognitiveServices"; import { DocServer } from "../../../DocServer"; import { Docs, DocUtils } from "../../../documents/Documents"; @@ -1515,70 +1515,66 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF // } - //Adds event listener so knows pointer is down and moving - onPointerMid = (e: React.PointerEvent): void => { - e.stopPropagation(); - e.preventDefault(); - this._isDragging = true; - document.removeEventListener("pointermove", this.onPointerMove); - document.addEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - document.addEventListener("pointerup", this.onPointerUp); - } + // //Adds event listener so knows pointer is down and moving + // onPointerMid = (e: React.PointerEvent): void => { + // e.stopPropagation(); + // e.preventDefault(); + // this._isDragging = true; + // const dragData = new DragManager.DocumentDragData([]); + // console.log(DragManager.StartDocumentDrag([], dragData, e.clientX, e.clientY)); + // } //Adds event listener so knows pointer is down and moving - onPointerBR = (e: React.PointerEvent): void => { + onPointerDown = (e: React.PointerEvent): void => { e.stopPropagation(); e.preventDefault(); - this._isDraggingBR = true; - document.removeEventListener("pointermove", this.onPointerMove); - document.addEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - document.addEventListener("pointerup", this.onPointerUp); + const corner = document.elementFromPoint(e.clientX, e.clientY)?.id; + if (corner) this._drag = corner; + const rect = document.getElementById('resizable'); + if (rect) { + console.log(this._drag); + setupMoveUpEvents(e.target, e, this.onPointerMove, (e) => { }, (e) => { }); + } } - //Adds event listener so knows pointer is down and moving - onPointerBL = (e: React.PointerEvent): void => { - e.stopPropagation(); - e.preventDefault(); - this._isDraggingBL = true; - document.removeEventListener("pointermove", this.onPointerMove); - document.addEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - document.addEventListener("pointerup", this.onPointerUp); - } + // //Adds event listener so knows pointer is down and moving + // onPointerBL = (e: React.PointerEvent): void => { + // e.stopPropagation(); + // e.preventDefault(); + // this._isDraggingBL = true; + // document.removeEventListener("pointermove", this.onPointerMove); + // document.addEventListener("pointermove", this.onPointerMove); + // document.removeEventListener("pointerup", this.onPointerUp); + // document.addEventListener("pointerup", this.onPointerUp); + // } - //Adds event listener so knows pointer is down and moving - onPointerTR = (e: React.PointerEvent): void => { - e.stopPropagation(); - e.preventDefault(); - this._isDraggingTR = true; - document.removeEventListener("pointermove", this.onPointerMove); - document.addEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - document.addEventListener("pointerup", this.onPointerUp); - } + // //Adds event listener so knows pointer is down and moving + // onPointerTR = (e: React.PointerEvent): void => { + // e.stopPropagation(); + // e.preventDefault(); + // this._isDraggingTR = true; + // document.removeEventListener("pointermove", this.onPointerMove); + // document.addEventListener("pointermove", this.onPointerMove); + // document.removeEventListener("pointerup", this.onPointerUp); + // document.addEventListener("pointerup", this.onPointerUp); + // } - //Adds event listener so knows pointer is down and moving - onPointerTL = (e: React.PointerEvent): void => { - e.stopPropagation(); - e.preventDefault(); - this._isDraggingTL = true; - document.removeEventListener("pointermove", this.onPointerMove); - document.addEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - document.addEventListener("pointerup", this.onPointerUp); - } + // //Adds event listener so knows pointer is down and moving + // onPointerTL = (e: React.PointerEvent): void => { + // e.stopPropagation(); + // e.preventDefault(); + // this._isDraggingTL = true; + // document.removeEventListener("pointermove", this.onPointerMove); + // document.addEventListener("pointermove", this.onPointerMove); + // document.removeEventListener("pointerup", this.onPointerUp); + // document.addEventListener("pointerup", this.onPointerUp); + // } //Removes all event listeners onPointerUp = (e: PointerEvent): void => { e.stopPropagation(); e.preventDefault(); - this._isDraggingTL = false; - this._isDraggingTR = false; - this._isDraggingBL = false; - this._isDraggingBR = false; - this._isDragging = false; + this._drag = ""; document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); } @@ -1590,105 +1586,106 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF // const newPanY = Math.min((1 - 1 / scale) * this.nativeHeight), Math.max(0, panY)); // } - @observable private _movementRight: number = 0; + @observable private _drag: string = ''; //Adjusts the value in NodeStore - onPointerMove = (e: PointerEvent): void => { + @action + onPointerMove = (e: PointerEvent) => { const activeItem = Cast(PresBox.Instance.childDocs[PresBox.Instance.itemIndex], Doc, null); const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); - const tagDocView = DocumentManager.Instance.getDocumentView(targetDoc); - e.stopPropagation(); - e.preventDefault(); const doc = document.getElementById('resizable'); - if (doc && tagDocView) { - - const scale = this.props.zoomScaling(); - const scale2 = tagDocView.childScaling(); - const scale3 = tagDocView.props.ScreenToLocalTransform().Scale; - const scale1 = NumCast(targetDoc._viewScale); - // const scale = this.props.zoomScaling(); - console.log("_viewScale: " + scale1); - console.log("_StLT: " + scale3); - console.log("zoomScaling: " + scale); - console.log("movementX: " + e.movementX); - console.log("movementX * scale: " + e.movementX * scale); + const rect = (e.target as any).getBoundingClientRect(); + const toNumber = (screen_delta: number, wh: number): number => { + // console.log(screen_delta); + // console.log(wh); + return screen_delta + wh; + }; + if (doc) { let height = doc.offsetHeight; let width = doc.offsetWidth; let top = doc.offsetTop; let left = doc.offsetLeft; - // const newHeightB = height += (e.movementY * NumCast(targetDoc._viewScale)); - // const newHeightT = height -= (e.movementY * NumCast(targetDoc._viewScale)); - // const newWidthR = width += (e.movementX * NumCast(targetDoc._viewScale)); - // const newWidthL = width -= (e.movementX * NumCast(targetDoc._viewScale)); - // const newLeft = left += (e.movementX * NumCast(targetDoc._viewScale)); - // const newTop = top += (e.movementY * NumCast(targetDoc._viewScale)); - // switch (this._drag) { - // case "": break; - // case "resizer-br": - // doc.style.height = newHeightB + 'px'; - // doc.style.width = newWidthR + 'px'; - // break; - // case "resizer-bl": - // doc.style.height = newHeightB + 'px'; - // doc.style.width = newWidthL + 'px'; - // doc.style.left = newLeft + 'px'; - // break; - // case "resizer-tr": - // doc.style.width = newWidthR + 'px'; - // doc.style.height = newHeightT + 'px'; - // doc.style.top = newTop + 'px'; - // case "resizer-tl": - // doc.style.width = newWidthL + 'px'; - // doc.style.height = newHeightT + 'px'; - // doc.style.top = newTop + 'px'; - // doc.style.left = newLeft + 'px'; - // case "resizable": - // doc.style.top = newTop + 'px'; - // doc.style.left = newLeft + 'px'; - // } - //Bottom right - if (this._isDraggingBR) { - const newHeight = height += (e.movementY * scale); - doc.style.height = newHeight + 'px'; - const newWidth = width += (e.movementX * scale); - doc.style.width = newWidth + 'px'; - // Bottom left - } else if (this._isDraggingBL) { - const newHeight = height += (e.movementY * scale); - doc.style.height = newHeight + 'px'; - const newWidth = width -= (e.movementX * scale); - doc.style.width = newWidth + 'px'; - const newLeft = left += (e.movementX * scale); - doc.style.left = newLeft + 'px'; - // Top right - } else if (this._isDraggingTR) { - const newWidth = width += (e.movementX * scale); - doc.style.width = newWidth + 'px'; - const newHeight = height -= (e.movementY * scale); - doc.style.height = newHeight + 'px'; - const newTop = top += (e.movementY * scale); - doc.style.top = newTop + 'px'; - // Top left - } else if (this._isDraggingTL) { - const newWidth = width -= (e.movementX * scale); - doc.style.width = newWidth + 'px'; - const newHeight = height -= (e.movementY * scale); - doc.style.height = newHeight + 'px'; - const newTop = top += (e.movementY * scale); - doc.style.top = newTop + 'px'; - const newLeft = left += (e.movementX * scale); - doc.style.left = newLeft + 'px'; - } else if (this._isDragging) { - const newTop = top += (e.movementY * scale); - doc.style.top = newTop + 'px'; - const newLeft = left += (e.movementX * scale); - doc.style.left = newLeft + 'px'; + switch (this._drag) { + case "": break; + case "resizer-br": + doc.style.width = toNumber(e.clientX - rect.x, width) + 'px'; + doc.style.height = toNumber(e.clientY - rect.y, height) + 'px'; + break; + case "resizer-bl": + doc.style.width = toNumber(e.clientX - rect.x, width) + 'px'; + doc.style.height = toNumber(e.clientY - rect.y, height) + 'px'; + doc.style.left = toNumber(e.clientY - rect.y, height) + 'px'; + break; + case "resizer-tr": + doc.style.width = toNumber(e.clientX - rect.x, width) + 'px'; + doc.style.height = toNumber(e.clientY - rect.y, height) + 'px'; + doc.style.top = toNumber(e.clientY - rect.y, top) + 'px'; + case "resizer-tl": + doc.style.width = toNumber(e.clientX - rect.x, width) + 'px'; + doc.style.height = toNumber(e.clientY - rect.y, height) + 'px'; + doc.style.top = toNumber(e.clientY - rect.x, top) + 'px'; + doc.style.left = toNumber(e.clientX - rect.y, left) + 'px'; + case "resizable": + doc.style.top = toNumber(e.clientY - rect.x, top) + 'px'; + doc.style.left = toNumber(e.clientX - rect.y, left) + 'px'; } this.updateList(targetDoc, activeItem["viewfinder-width-indexed"], width); this.updateList(targetDoc, activeItem["viewfinder-height-indexed"], height); this.updateList(targetDoc, activeItem["viewfinder-top-indexed"], top); this.updateList(targetDoc, activeItem["viewfinder-left-indexed"], left); + return false; } + return true; + + + // const activeItem = Cast(PresBox.Instance.childDocs[PresBox.Instance.itemIndex], Doc, null); + // const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); + // const tagDocView = DocumentManager.Instance.getDocumentView(targetDoc); + // e.stopPropagation(); + // e.preventDefault(); + // if (doc && tagDocView) { + + // const scale = this.props.zoomScaling(); + // const scale2 = tagDocView.childScaling(); + // const scale3 = tagDocView.props.ScreenToLocalTransform().Scale; + // const scale1 = NumCast(targetDoc._viewScale); + // // const scale = this.props.zoomScaling(); + // console.log("_viewScale: " + scale1); + // console.log("_StLT: " + scale3); + // console.log("zoomScaling: " + scale); + // console.log("movementX: " + e.movementX); + // console.log("movementX * scale: " + e.movementX * scale); + // let height = doc.offsetHeight; + // let width = doc.offsetWidth; + // let top = doc.offsetTop; + // let left = doc.offsetLeft; + // switch (this._drag) { + // case "": break; + // case "resizer-br": + // doc.style.height = newHeightB + 'px'; + // doc.style.width = newWidthR + 'px'; + // break; + // case "resizer-bl": + // doc.style.height = newHeightB + 'px'; + // doc.style.width = newWidthL + 'px'; + // doc.style.left = newLeft + 'px'; + // break; + // case "resizer-tr": + // doc.style.width = newWidthR + 'px'; + // doc.style.height = newHeightT + 'px'; + // doc.style.top = newTop + 'px'; + // case "resizer-tl": + // doc.style.width = newWidthL + 'px'; + // doc.style.height = newHeightT + 'px'; + // doc.style.top = newTop + 'px'; + // doc.style.left = newLeft + 'px'; + // case "resizable": + // doc.style.top = newTop + 'px'; + // doc.style.left = newLeft + 'px'; + // } + + + // } } @action @@ -1697,7 +1694,7 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF if (x && x.length >= NumCast(doc.currentFrame) + 1) { x[NumCast(doc.currentFrame)] = val; list = x; - } else { + } else if (doc && x) { x.length = NumCast(doc.currentFrame) + 1; x[NumCast(doc.currentFrame)] = val; list = x; @@ -1709,18 +1706,18 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF const activeItem = Cast(PresBox.Instance.childDocs[PresBox.Instance.itemIndex], Doc, null); const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); if (activeItem && activeItem.zoomProgressivize) { - const vfLeft: number = PresBox.Instance.checkList(activeItem, activeItem["viewfinder-left-indexed"]); - const vfWidth: number = PresBox.Instance.checkList(activeItem, activeItem["viewfinder-width-indexed"]); - const vfTop: number = PresBox.Instance.checkList(activeItem, activeItem["viewfinder-top-indexed"]); - const vfHeight: number = PresBox.Instance.checkList(activeItem, activeItem["viewfinder-height-indexed"]); + const vfLeft: number = !activeItem ? 0 : PresBox.Instance.checkList(targetDoc, activeItem["viewfinder-left-indexed"]); + const vfWidth: number = !activeItem ? 0 : PresBox.Instance.checkList(targetDoc, activeItem["viewfinder-width-indexed"]); + const vfTop: number = !activeItem ? 0 : PresBox.Instance.checkList(targetDoc, activeItem["viewfinder-top-indexed"]); + const vfHeight: number = !activeItem ? 0 : PresBox.Instance.checkList(targetDoc, activeItem["viewfinder-height-indexed"]); return ( <> - {!activeItem.editZoomProgressivize ? (null) : <div id="resizable" className="resizable" onPointerDown={this.onPointerMid} style={{ width: vfWidth, height: vfHeight, top: vfTop, left: vfLeft, position: 'absolute' }}> + {!activeItem.editZoomProgressivize ? (null) : <div id="resizable" className="resizable" onPointerDown={this.onPointerDown} style={{ width: vfWidth, height: vfHeight, top: vfTop, left: vfLeft, position: 'absolute' }}> <div className='resizers'> - <div id="resizer-tl" className='resizer top-left' onPointerDown={this.onPointerTL}></div> - <div id="resizer-tr" className='resizer top-right' onPointerDown={this.onPointerTR}></div> - <div id="resizer-bl" className='resizer bottom-left' onPointerDown={this.onPointerBL}></div> - <div id="resizer-br" className='resizer bottom-right' onPointerDown={this.onPointerBR}></div> + <div id="resizer-tl" className='resizer top-left' onPointerDown={this.onPointerDown}></div> + <div id="resizer-tr" className='resizer top-right' onPointerDown={this.onPointerDown}></div> + <div id="resizer-bl" className='resizer bottom-left' onPointerDown={this.onPointerDown}></div> + <div id="resizer-br" className='resizer bottom-right' onPointerDown={this.onPointerDown}></div> </div> </div>} </> diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index a87b0e466..5346efe0e 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -153,7 +153,6 @@ $light-background: #ececec; margin-left: 5px; margin-top: 5px; margin-bottom: 5px; - margin-right: 5px; width: max-content; justify-content: center; align-items: center; @@ -161,6 +160,29 @@ $light-background: #ececec; padding-left: 10px; } + .ribbon-propertyUpDown { + height: 20; + width: 20; + margin-top: 5px; + display: grid; + grid-template-rows: 10px 10px; + + .ribbon-propertyUpDownItem { + color: white; + display: flex; + justify-content: center; + align-items: center; + height: 100%; + width: 100%; + background: black; + } + + .ribbon-propertyUpDownItem:hover { + background: darkgrey; + transform: scale(1.05); + } + } + .presBox-subheading { font-size: 11; font-weight: 400; @@ -254,6 +276,18 @@ $light-background: #ececec; width: 100%; } + .presBox-input { + width: 30; + height: 100%; + background: none; + border: none; + text-align: right; + } + + .presBox-input:focus { + outline: none; + } + .ribbon-frameSelector { border: black solid 1px; width: 60px; @@ -399,11 +433,9 @@ $light-background: #ececec; grid-template-rows: max-content auto; justify-self: center; margin-top: 10px; - /* padding-left: 10px; */ padding-right: 10px; letter-spacing: normal; width: 100%; - /* max-width: 100%; */ height: max-content; font-weight: 500; position: relative; @@ -412,9 +444,33 @@ $light-background: #ececec; border-bottom: solid 1px darkgrey; .presBox-dropdown:hover { - border: solid 1px #378AD8; - border-bottom-left-radius: 0px; + border: solid 1px $dark-blue; + + .presBox-dropdownIcon { + color: $dark-blue; + } + } + + .presBox-dropdown { + display: grid; + grid-template-columns: auto 20%; + position: relative; + border: solid 1px black; + background-color: $light-background; + border-radius: 5px; + font-size: 10; + height: 25; + padding-left: 5px; + align-items: center; + margin-top: 5px; + margin-bottom: 5px; + font-weight: 200; + width: 100%; + min-width: max-content; + max-width: 200px; + overflow: visible; + .presBox-dropdownOption { font-size: 11; display: block; @@ -431,7 +487,7 @@ $light-background: #ececec; .presBox-dropdownOption.active { position: relative; - background-color: #aedef8; + background-color: $light-blue; } .presBox-dropdownOptions { @@ -449,34 +505,6 @@ $light-background: #ececec; } .presBox-dropdownIcon { - color: #378AD8; - } - } - - .presBox-dropdown { - display: grid; - grid-template-columns: auto 20%; - position: relative; - border: solid 1px black; - background-color: $light-background; - border-radius: 5px; - font-size: 10; - height: 25; - padding-left: 5px; - align-items: center; - margin-top: 5px; - margin-bottom: 5px; - font-weight: 200; - width: 100%; - min-width: max-content; - max-width: 200px; - overflow: visible; - - .presBox-dropdownOptions { - display: none; - } - - .presBox-dropdownIcon { position: relative; color: black; align-self: center; diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index ff2be6b4e..3083bc6ec 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -55,6 +55,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @observable private presentTools: boolean = false; @observable private pathBoolean: boolean = false; @observable private expandBoolean: boolean = false; + @observable private openMovementDropdown: boolean = false; + @observable private openEffectDropdown: boolean = false; @computed get childDocs() { return DocListCast(this.dataDoc[this.fieldKey]); } @computed get itemIndex() { return NumCast(this.rootDoc._itemIndex); } @@ -101,6 +103,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> this.layoutDoc._gridGap = 5; } + onComponentUnmount() { + document.removeEventListener("keydown", this.keyEvents, true); + console.log("when does this happen?"); + } + updateCurrentPresentation = () => { Doc.UserDoc().activePresentation = this.rootDoc; } @@ -351,7 +358,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } @action togglePath = () => this.pathBoolean = !this.pathBoolean; - @action toggleExpand = () => this.expandBoolean = !this.expandBoolean; + @action toggleExpandMode = () => { + this.rootDoc.expandBoolean = !this.rootDoc.expandBoolean; + this.childDocs.forEach((doc) => { + if (this.rootDoc.expandBoolean) doc.presExpandInlineButton = true; + else if (!this.rootDoc.expandBoolean) doc.presExpandInlineButton = false; + }); + }; /** * The function that starts the presentation at the given index, also checking if actions should be applied @@ -448,6 +461,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } else { doc.aliasOf instanceof Doc && (doc.presentationTargetDoc = doc.aliasOf); !this.childDocs.includes(doc) && (doc.presZoomButton = true); + if (this.rootDoc.expandBoolean) doc.presExpandInlineButton = true; } }); return true; @@ -656,16 +670,22 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } // Converts seconds to ms and updates presTransition - setTransitionTime = (number: String) => { - const timeInMS = Number(number) * 1000; + setTransitionTime = (number: String, change?: number) => { + let timeInMS = Number(number) * 1000; + if (change) timeInMS += change; + if (timeInMS < 0) timeInMS = 100; + if (timeInMS > 10000) timeInMS = 10000; const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); if (targetDoc) targetDoc.presTransition = timeInMS; } // Converts seconds to ms and updates presDuration - setDurationTime = (number: String) => { - const timeInMS = Number(number) * 1000; + setDurationTime = (number: String, change?: number) => { + let timeInMS = Number(number) * 1000; + if (change) timeInMS += change; + if (timeInMS < 0) timeInMS = 100; + if (timeInMS > 20000) timeInMS = 20000; const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); if (targetDoc) targetDoc.presDuration = timeInMS; @@ -676,19 +696,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); if (activeItem && targetDoc) { - const transitionSpeed = targetDoc.presTransition ? String(Number(targetDoc.presTransition) / 1000) : 0.5; + let transitionSpeed = targetDoc.presTransition ? String(Number(targetDoc.presTransition) / 1000) : 0.5; let duration = targetDoc.presDuration ? String(Number(targetDoc.presDuration) / 1000) : 2; if (targetDoc.type === DocumentType.AUDIO) duration = NumCast(targetDoc.duration); const effect = targetDoc.presEffect ? targetDoc.presEffect : 'None'; activeItem.presMovement = activeItem.presMovement ? activeItem.presMovement : 'Zoom'; return ( - <div className={`presBox-ribbon ${this.transitionTools && this.layoutDoc.presStatus === "edit" ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> + <div className={`presBox-ribbon ${this.transitionTools && this.layoutDoc.presStatus === "edit" ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onClick={action(e => { e.stopPropagation(); this.openMovementDropdown = false; this.openEffectDropdown = false; })}> <div className="ribbon-box"> Movement - <div className="presBox-dropdown" onPointerDown={e => e.stopPropagation()}> + <div className="presBox-dropdown" onClick={action(e => { e.stopPropagation(); this.openMovementDropdown = !this.openMovementDropdown })} style={{ borderBottomLeftRadius: this.openMovementDropdown ? 0 : 5 }}> {activeItem.presMovement} <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2 }} icon={"angle-down"} /> - <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onClick={e => e.stopPropagation()}> + <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onPointerDown={e => e.stopPropagation()} style={{ display: this.openMovementDropdown ? "grid" : "none" }}> <div className={`presBox-dropdownOption ${activeItem.presMovement === 'None' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('none')}>None</div> <div className={`presBox-dropdownOption ${activeItem.presMovement === 'Zoom' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('zoom')}>Pan and Zoom</div> <div className={`presBox-dropdownOption ${activeItem.presMovement === 'Pan' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('pan')}>Pan</div> @@ -696,8 +716,21 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> </div> </div> <div className="ribbon-doubleButton" style={{ display: activeItem.presMovement === 'Pan' || activeItem.presMovement === 'Zoom' ? "inline-flex" : "none" }}> - <div className="presBox-subheading" >Transition Speed</div> - <div className="ribbon-property"> {transitionSpeed} s </div> + <div className="presBox-subheading">Transition Speed</div> + <div className="ribbon-property"> + <input className="presBox-input" + type="text" value={transitionSpeed} + onFocus={() => { document.removeEventListener("keydown", this.keyEvents, true); }} + onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { if (Number(e.target.value) >= 0 && Number(e.target.value) <= 10 && !isNaN(Number(e.target.value)) || e.target.value === '') this.setTransitionTime(e.target.value) })} /> s + </div> + <div className="ribbon-propertyUpDown"> + <div className="ribbon-propertyUpDownItem" onClick={() => this.setTransitionTime(String(duration), 1000)}> + <FontAwesomeIcon icon={"caret-up"} /> + </div> + <div className="ribbon-propertyUpDownItem" onClick={() => this.setTransitionTime(String(duration), -1000)}> + <FontAwesomeIcon icon={"caret-down"} /> + </div> + </div> </div> <input type="range" step="0.1" min="0.1" max="10" value={transitionSpeed} className={`toolbar-slider ${activeItem.presMovement === 'Pan' || activeItem.presMovement === 'Zoom' ? "" : "none"}`} id="toolbar-slider" onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setTransitionTime(e.target.value); }} /> <div className={`slider-headers ${activeItem.presMovement === 'Pan' || activeItem.presMovement === 'Zoom' ? "" : "none"}`}> @@ -714,9 +747,22 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> </div> <div className="ribbon-doubleButton" > <div className="presBox-subheading">Slide Duration</div> - <div className="ribbon-property"> {duration} s </div> + <div className="ribbon-property"> + <input className="presBox-input" + type="text" value={duration} + onFocus={() => { document.removeEventListener("keydown", this.keyEvents, true); }} + onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { if (Number(e.target.value) >= 0 && Number(e.target.value) <= 20 && !isNaN(Number(e.target.value)) || e.target.value === '') this.setDurationTime(e.target.value) })} /> s + </div> + <div className="ribbon-propertyUpDown"> + <div className="ribbon-propertyUpDownItem" onClick={() => this.setDurationTime(String(duration), 1000)}> + <FontAwesomeIcon icon={"caret-up"} /> + </div> + <div className="ribbon-propertyUpDownItem" onClick={() => this.setDurationTime(String(duration), -1000)}> + <FontAwesomeIcon icon={"caret-down"} /> + </div> + </div> </div> - <input type="range" step="0.1" min="0.1" max="10" value={duration} style={{ display: targetDoc.type === DocumentType.AUDIO ? "none" : "block" }} className={"toolbar-slider"} id="duration-slider" onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setDurationTime(e.target.value); }} /> + <input type="range" step="0.1" min="0.1" max="20" value={duration} style={{ display: targetDoc.type === DocumentType.AUDIO ? "none" : "block" }} className={"toolbar-slider"} id="duration-slider" onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setDurationTime(e.target.value); }} /> <div className={"slider-headers"} style={{ display: targetDoc.type === DocumentType.AUDIO ? "none" : "grid" }}> <div className="slider-text">Short</div> <div className="slider-text">Medium</div> @@ -725,12 +771,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> </div> <div className="ribbon-box"> Effects - <div className="presBox-dropdown" - onPointerDown={e => e.stopPropagation()} - > + <div className="presBox-dropdown" onClick={action(e => { e.stopPropagation(); this.openEffectDropdown = !this.openEffectDropdown })} style={{ borderBottomLeftRadius: this.openMovementDropdown ? 0 : 5 }}> {effect} <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2 }} icon={"angle-down"} /> - <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onClick={e => e.stopPropagation()}> + <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} style={{ display: this.openEffectDropdown ? "grid" : "none" }} onPointerDown={e => e.stopPropagation()}> <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={() => targetDoc.presEffect = 'None'}>None</div> <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={() => targetDoc.presEffect = 'Fade'}>Fade In</div> <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={() => targetDoc.presEffect = 'Flip'}>Flip</div> @@ -761,7 +805,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> Apply to all </div> </div> - </div> + </div > ); } } @@ -793,9 +837,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } }); } - - private inputRef = React.createRef<HTMLInputElement>(); - @computed get optionsDropdown() { const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); @@ -871,13 +912,18 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @computed get newDocumentDropdown() { return ( <div> - <div className={"presBox-ribbon"} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> + <div className={"presBox-ribbon"} onClick={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> <div className="ribbon-box"> Slide Title: <br></br> - <input className="ribbon-textInput" placeholder="..." type="text" name="fname" ref={this.inputRef} onChange={(e) => { - e.stopPropagation(); - runInAction(() => this.title = e.target.value); - }}></input> + <input className="ribbon-textInput" placeholder="..." type="text" name="fname" + onFocus={() => { + document.removeEventListener("keydown", this.keyEvents, true); + }} + onChange={(e) => { + e.stopPropagation(); + e.preventDefault(); + runInAction(() => this.title = e.target.value); + }}></input> </div> <div className="ribbon-box"> Choose type: @@ -1298,16 +1344,15 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } @action - checkList = (doc: Doc, list: any): number => { + checkList = (doc: Doc, list: any) => { const x: List<number> = list; if (x && x.length >= NumCast(doc.currentFrame) + 1) { return x[NumCast(doc.currentFrame)]; - } else if (doc) { + } else if (doc && x) { x.length = NumCast(doc.currentFrame) + 1; x[NumCast(doc.currentFrame)] = x[NumCast(doc.currentFrame) - 1]; return x[NumCast(doc.currentFrame)]; } - } @computed get progressivizeChildDocs() { @@ -1404,8 +1449,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <FontAwesomeIcon icon={"exchange-alt"} /> </div> </Tooltip> - <Tooltip title={<><div className="dash-tooltip">{this.expandBoolean ? "Minimize all" : "Expand all"}</div></>}> - <div style={{ opacity: this.childDocs.length > 0 ? 1 : 0.3 }} className={`toolbar-button ${this.expandBoolean ? "active" : ""}`} onClick={() => { if (this.childDocs.length > 0) this.toggleExpand(); this.childDocs.forEach((doc, ind) => { if (this.expandBoolean) doc.presExpandInlineButton = true; else doc.presExpandInlineButton = false; }); }}> + <Tooltip title={<><div className="dash-tooltip">{this.rootDoc.expandBoolean ? "Minimize all" : "Expand all"}</div></>}> + <div className={`toolbar-button ${this.rootDoc.expandBoolean ? "active" : ""}`} onClick={this.toggleExpandMode}> <FontAwesomeIcon icon={"eye"} /> </div> </Tooltip> diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index a6dbb76ef..42b43b402 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -233,13 +233,23 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc private _itemRef: React.RefObject<HTMLDivElement> = React.createRef(); private _dragRef: React.RefObject<HTMLDivElement> = React.createRef(); + @action headerDown = (e: React.PointerEvent<HTMLDivElement>) => { - const element = document.elementFromPoint(e.clientX, e.clientY)?.parentElement; + const element1 = document.elementFromPoint(e.clientX, e.clientY)?.parentElement; + const element = e.target as any; e.stopPropagation(); e.preventDefault(); if (element) { if (PresBox.Instance._eleArray.includes(element)) { setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction); + } else { + PresBox.Instance._selectedArray = []; + PresBox.Instance._selectedArray.push(this.rootDoc); + PresBox.Instance._eleArray = []; + PresBox.Instance._eleArray.push(this._itemRef.current!); + PresBox.Instance._dragArray = []; + PresBox.Instance._dragArray.push(this._dragRef.current!); + setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction); } } } |